From 9339deb833f6c56e7f1097e77036ef17d5791e4f Mon Sep 17 00:00:00 2001 From: Susanne Date: Wed, 7 Aug 2019 12:31:36 +0300 Subject: [PATCH 1/5] actual status of Navier Stokes without diffusionInterfac --- CMakeLists.txt | 3 +- File | 0 .../immersed_bnd_cond_particle.h | 146 + .../immersed_bnd_cond_particle_impl.h | 1344 ++++++++ .../loc_to_glob_mapper_particle.h | 305 ++ .../loc_to_glob_mapper_particle_impl.h | 2775 +++++++++++++++++ .../loc_to_glob_mapper_particle_tools.h | 330 ++ .../fv1/moving_particle/meanID_tools.h | 1732 ++++++++++ .../fv1/moving_particle/moving_particle.h | 652 ++++ .../moving_particle/moving_particle_impl.h | 913 ++++++ .../moving_particle/moving_particle_tools.h | 502 +++ incompressible/fv1/navier_stokes_fv1.cpp | 81 +- incompressible/fv1/navier_stokes_fv1.h | 6 + incompressible/fv1/navier_stokes_fv1_FV1.cpp | 1130 +++++++ incompressible/fv1/stabilization.cpp | 663 +++- incompressible/fv1/stabilization.h | 79 +- .../two_phase_flow/interface_handler_2pf.h | 176 ++ .../interface_handler_2pf_impl.h | 566 ++++ .../two_phase_flow/loc_to_glob_mapper_2pf.h | 127 + .../loc_to_glob_mapper_2pf_impl.h | 386 +++ .../fv1/two_phase_flow/two_phase_flow.h | 216 ++ .../fv1/two_phase_flow/two_phase_flow_impl.h | 329 ++ .../incompressible_navier_stokes_plugin.cpp | 5 +- .../particle_laden_flow_plugin Kopie.cpp | 414 +++ incompressible/particle_laden_flow_plugin.cpp | 366 +++ incompressible/particle_laden_flow_plugin.h | 48 + .../particle_laden_flow_plugin_origJonas.cpp | 414 +++ register_navier_stokes.h | 1 + upwind.cpp | 472 ++- upwind.h | 38 +- upwind_interface.h | 128 +- 31 files changed, 14217 insertions(+), 130 deletions(-) create mode 100644 File create mode 100644 incompressible/fv1/moving_particle/immersed_bnd_cond_particle.h create mode 100644 incompressible/fv1/moving_particle/immersed_bnd_cond_particle_impl.h create mode 100644 incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h create mode 100644 incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h create mode 100644 incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_tools.h create mode 100644 incompressible/fv1/moving_particle/meanID_tools.h create mode 100644 incompressible/fv1/moving_particle/moving_particle.h create mode 100644 incompressible/fv1/moving_particle/moving_particle_impl.h create mode 100644 incompressible/fv1/moving_particle/moving_particle_tools.h create mode 100644 incompressible/fv1/navier_stokes_fv1_FV1.cpp create mode 100644 incompressible/fv1/two_phase_flow/interface_handler_2pf.h create mode 100644 incompressible/fv1/two_phase_flow/interface_handler_2pf_impl.h create mode 100644 incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf.h create mode 100644 incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf_impl.h create mode 100644 incompressible/fv1/two_phase_flow/two_phase_flow.h create mode 100644 incompressible/fv1/two_phase_flow/two_phase_flow_impl.h create mode 100644 incompressible/particle_laden_flow_plugin Kopie.cpp create mode 100644 incompressible/particle_laden_flow_plugin.cpp create mode 100644 incompressible/particle_laden_flow_plugin.h create mode 100644 incompressible/particle_laden_flow_plugin_origJonas.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f3c4d5e..67db2db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,8 @@ set(SOURCES navier_stokes_base.cpp incompressible/fvcr/register_fvcr.cpp incompressible/fe/register_fe.cpp - incompressible/incompressible_navier_stokes_plugin.cpp) + incompressible/incompressible_navier_stokes_plugin.cpp + incompressible/particle_laden_flow_plugin.cpp) ################################################################################ diff --git a/File b/File new file mode 100644 index 0000000..e69de29 diff --git a/incompressible/fv1/moving_particle/immersed_bnd_cond_particle.h b/incompressible/fv1/moving_particle/immersed_bnd_cond_particle.h new file mode 100644 index 0000000..6ae16cf --- /dev/null +++ b/incompressible/fv1/moving_particle/immersed_bnd_cond_particle.h @@ -0,0 +1,146 @@ +/* + * particle_bnd_cond.h + * + * Created on: 30.01.2015 + * Author: suze + */ + +#ifndef PARTICLE_BND_COND_H_ +#define PARTICLE_BND_COND_H_ + +#ifdef UG_PARALLEL + #include "lib_grid/parallelization/load_balancer_util.h" +#endif + +#include "../../incompressible_navier_stokes_base.h" + + +#include "lib_disc/spatial_disc/immersed_util/immersed_interface_base.h" + +namespace ug{ +namespace NavierStokes{ + +template +class ParticleBndCond : public IInterfaceBndCond +{ + public: + /// World dimension + static const int dim = TDomain::dim; + + /// abbreviation for pressure + static const size_t _P_ = dim; + + /// used boundary face type + typedef typename DimFV1FTGeometry >::BF interfaceBF; + + /// call base class constructor + + ParticleBndCond(SmartPtr > spMaster, + SmartPtr > localHandler); + + public: + /// type of trial space for each function used + void prepare_setting(const std::vector& vLfeID, bool bNonRegularGrid); + + /// prepares the element loop + template + void prep_elem_loop(const ReferenceObjectID roid, const int si){ + } + + /// prepares the element for evaluation + template + void prep_elem(const LocalVector& u, GridObject* elem, + const ReferenceObjectID roid, const MathVector vCornerCoords[]); + + /// finishes the element loop + template + void fsh_elem_loop(){ } + + /// adds the stiffness part to the local jacobian + template + void add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, + const MathVector vCornerCoords[]); + + void add_jac_A_elem_Quadri_for2(LocalMatrix& J, const LocalVector locU); + + /// adds the stiffness part to the local defect + template + void add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, + const MathVector vCornerCoords[]); + void add_def_A_elem_Quadri_for2(LocalVector& locD, const LocalVector locU); + void add_quadri_to_defect(LocalVector& d, const LocalVector& quadriD); + + template + void add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, + const MathVector vCornerCoords[]); + + template + void add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, + const MathVector vCornerCoords[]); + + template + void add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoords[]); + + + void diffusive_flux_Jac(const size_t ip, const interfaceBF& bf, LocalMatrix& J, const LocalVector& u); + void diffusive_flux_Jac_for2(const size_t ip, const interfaceBF& bf, LocalMatrix& J, const LocalVector& u); + void diffusive_flux_Jac_rot(const size_t ip, const interfaceBF& bf, LocalMatrix& J, const LocalVector& u, number importDensity); + + void diffusive_flux_defect(const size_t ip, const interfaceBF& bf, LocalVector& d, const LocalVector& u); + void diffusive_flux_defect_rot(const size_t ip, const interfaceBF& bf, LocalVector& d, const LocalVector& u); + + void remove_equations(LocalVector& d, std::vector vFctID, std::vector vDofID); + void remove_equations(LocalMatrix& J, std::vector vFctID, std::vector vDofID); + + int get_prtIndex() { return m_spInterfaceHandlerLocal->get_prtIndex(); } + + number get_density(int prtIndex) { return m_spInterfaceHandlerLocal->get_density(prtIndex); } + number get_density_fluid() { return m_spInterfaceHandlerLocal->get_density_fluid(); } + number get_kinVisc_fluid() { return m_spInterfaceHandlerLocal->get_kinVisc_fluid(); } + + void copy_local_couplings_jac() + { m_spInterfaceHandlerLocal->set_local_couplings_jac(rotJ_ind, rotJ_rot); } + void copy_local_couplings_def() + { m_spInterfaceHandlerLocal->set_local_couplings_def(rotD); } + + void write_QuadriSol(const LocalVector origU); + + /// remaps entries for Quadri+Tri-combination of CUT_BY_2_INTERFACE element + size_t remap_for2(size_t dof); + + /// destructor + ~ParticleBndCond(){}; + + protected: + // master element disc + SmartPtr > m_spMaster; + + // member from base class + SmartPtr > m_spInterfaceHandlerLocal; + + // local data for assembling: + LocalMatrix rotJ_ind; + LocalMatrix rotJ_rot; + LocalVector rotD; + + /// Boundary integration points of the viscosity and the density +// std::vector > m_vLocIP; +// std::vector > m_vGloIP; + + protected: + void register_all(bool bHang); + template + void register_func(); + +}; + + + +} // end namespace NavierStokes +} // end namespace ug + +#include "immersed_bnd_cond_particle_impl.h" + + + +#endif /* PARTICLE_BND_COND_H_ */ diff --git a/incompressible/fv1/moving_particle/immersed_bnd_cond_particle_impl.h b/incompressible/fv1/moving_particle/immersed_bnd_cond_particle_impl.h new file mode 100644 index 0000000..8bf7aa3 --- /dev/null +++ b/incompressible/fv1/moving_particle/immersed_bnd_cond_particle_impl.h @@ -0,0 +1,1344 @@ +/* + * particle_bnd_cond_impl.h + * + * Created on: 30.01.2015 + * Author: suze + */ + +#ifndef PARTICLE_BND_COND_IMPL_H_ +#define PARTICLE_BND_COND_IMPL_H_ + + + +namespace ug{ +namespace NavierStokes{ + +//////////////////////////////////////////////////////////////////////////////// +// Constructor - set default values +//////////////////////////////////////////////////////////////////////////////// +// see 'no_normal_stress_outflow.cpp': +template +ParticleBndCond:: +ParticleBndCond(SmartPtr > spMaster, + SmartPtr > localHandler) + : IInterfaceBndCond(spMaster->symb_fcts(), spMaster->symb_subsets(), localHandler), + m_spMaster(spMaster), + m_spInterfaceHandlerLocal(localHandler) +{ +// update assemble functions + register_all(false); +} + +template +void ParticleBndCond:: +prepare_setting(const std::vector& vLfeID, bool bNonRegularGrid) +{ + // do nothing... +} + +// see 'NavierStokesNoNormalStressOutflowFV1::prep_elem()' +template +template +void ParticleBndCond:: +prep_elem(const LocalVector& u, GridObject* elem, const ReferenceObjectID roid, const MathVector vCornerCoords[]) +{ + +// Update Geometry for this element + static TFVGeom& geo = GeomProvider::get(LFEID(LFEID::LAGRANGE, dim, 1), 1); + + geo.update(elem, vCornerCoords, &(this->subset_handler())); + +} + + +//////////////////////////////////////////////////////////////////////////////// +// methods for adapting jacobian due to the bnd cond +//////////////////////////////////////////////////////////////////////////////// + +// removes the equations with IDs in 'vFctID' locally assembled in the corners of 'vDofID' +template +void ParticleBndCond:: +remove_equations(LocalMatrix& J, std::vector vFctID, std::vector vDofID) +{ + + for(size_t i = 0; i < vDofID.size(); ++i) + for(size_t j = 0; j < vFctID.size(); ++j) + for(size_t fct = 0; fct < J.num_all_row_fct(); ++fct) + for(size_t dof = 0; dof < J.num_all_row_dof(fct); ++dof) + J(vFctID[j], vDofID[i], fct, dof) = 0.0; + +} + + +// see 'NavierStokesNoNormalStressOutflowFV1::diffusive_flux_Jac()' +template +void ParticleBndCond:: +diffusive_flux_Jac_rot(const size_t ip, const interfaceBF& bf, LocalMatrix& J, const LocalVector& u, number importDensity) +{ + + MathMatrix diffFlux, tang_diffFlux; + MathVector normalStress; + MathMatrix RotIndMat, RotRotMat; + MathVector angularVel; + RotIndMat = 0.0; RotRotMat = 0.0; angularVel = 0.0; + + UG_LOG("*RotIndMat = " << RotIndMat << "\n"); + UG_LOG("*RotRotMat = " << RotRotMat << "\n"); + UG_LOG("*angularVel = " << angularVel << "\n"); + + MathMatrix rotationMatIP_transposed = m_spInterfaceHandlerLocal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_ip(bf.node_id())); + Transpose(rotationMatIP_transposed); + + UG_LOG("start sh-loop for = " << ip << "\n"); + + for(size_t sh = 0; sh < bf.num_sh(); ++sh) // loop shape functions + { + // 1. Compute the total flux + // - add \nabla u *n + MatSet (diffFlux, 0); + MatDiagSet (diffFlux, VecDot (bf.global_grad(sh), bf.normal())); + + // - add (\nabla u)^T*n + if( !m_spMaster->laplace()) + for (size_t d1 = 0; d1 < (size_t)dim; ++d1) + for (size_t d2 = 0; d2 < (size_t)dim; ++d2) + diffFlux(d1,d2) += bf.global_grad(sh)[d1] * bf.normal()[d2]; + + // Scale by viscosity + diffFlux *= get_kinVisc_fluid(); + + // 2. compute r x [\sigma(u)]*n + // => compute local couplings between rotation and translation/fluid + MatMultiply(RotIndMat, rotationMatIP_transposed, diffFlux); + UG_LOG("rotationMatIP_transposed " << rotationMatIP_transposed << "\n"); + UG_LOG(". diffFlux " << diffFlux << "\n"); + UG_LOG("= RotIndMat " << RotIndMat << "\n"); + + // 3. compute r x [\sigma(w x r)]*n + if ( m_spInterfaceHandlerLocal->lies_onInterface(sh) ) + { + UG_LOG("sh = " << sh << "on interface\n"); + UG_LOG("rotationMatIP_transposed " << rotationMatIP_transposed << "\n"); + + // 3.1 compute r x [...]*n + MatMultiply(RotRotMat, rotationMatIP_transposed, diffFlux); + + // 3.2 compute [\sigma(w x r)]*n + MathMatrix rotationMatSH = m_spInterfaceHandlerLocal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(sh)); + MatMultiply(RotRotMat, RotRotMat, rotationMatSH); + UG_LOG("rotationMatSH " << rotationMatSH << "\n"); + + // 3.3 compute (w x r)*n for continuity equation + // transpose in order to multiply from left: + // n^T*rotationMatSH = rotationMatSH^T*n + Transpose(rotationMatSH); + MatVecMult(angularVel, rotationMatSH, bf.normal()); + UG_LOG("transposed rotationMatSH " << rotationMatSH << "\n"); + UG_LOG("bf.normal() " << bf.normal() << "\n"); + UG_LOG("__angularVel(2. komp = 0?? " << angularVel << "\n"); + + } + + // 4. Change sign, since force acts onto particle in inverse direction: + //diffFlux *= -1.0; + + // 5. Add flux to local Jacobian + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + for(size_t d2 = 0; d2 < (size_t)dim; ++d2) + { + // write transJ: + J(d1, bf.node_id(), d2, sh) += diffFlux(d1, d2); + rotJ_ind(d1, bf.node_id(), d2, sh) += RotIndMat(d1, d2); + // write rotJ: + rotJ_rot(d1, bf.node_id(), d2, sh) += RotRotMat(d1, d2); + + } + + // 6. Add pressure term to local Jacobian + // 6.1. ----> r x p*n wird NICHT assembliert! + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + J(d1, bf.node_id(), _P_, sh) -= bf.shape(sh) * bf.normal()[d1]; + + + // 7. The continuity equation + VecScale(angularVel, angularVel, bf.shape(sh)); + for (size_t d2 = 0; d2 < (size_t)dim; ++d2) + rotJ_ind(_P_, bf.node_id(), d2, sh) += angularVel[d2]; + + UG_LOG("angularVel(2. komp = 0?? " << angularVel << "\n"); + + } + + + UG_LOG("RotIndMat " << RotIndMat << "\n"); + UG_LOG("RotRotMat " << RotRotMat << "\n"); + + if ( m_spInterfaceHandlerLocal->m_vInterfaceID[0] == m_spInterfaceHandlerLocal->m_vInterfaceID[1]) + UG_THROW("end sh-loop for = " << ip << "\n"); + +} + + +// see 'NavierStokesNoNormalStressOutflowFV1::diffusive_flux_Jac()' +template +void ParticleBndCond:: +diffusive_flux_Jac(const size_t ip, const interfaceBF& bf, LocalMatrix& J, const LocalVector& u) +{ + + MathMatrix diffFlux, tang_diffFlux; + MathVector normalStress; + + for(size_t sh = 0; sh < bf.num_sh(); ++sh) // loop shape functions + { + // 1. Compute the total flux + // - add \nabla u + MatSet (diffFlux, 0); + MatDiagSet (diffFlux, VecDot (bf.global_grad(sh), bf.normal())); + + + // - add (\nabla u)^T + if( !m_spMaster->laplace()) + for (size_t d1 = 0; d1 < (size_t)dim; ++d1) + for (size_t d2 = 0; d2 < (size_t)dim; ++d2) + diffFlux(d1,d2) += bf.global_grad(sh)[d1] * bf.normal()[d2]; + + // 2. Scale by viscosity + diffFlux *= get_kinVisc_fluid(); + + // 3. Change sign, since force acts onto particle in inverse direction: + //diffFlux *= -1.0; + + // 4. Add flux to local Jacobian + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + for(size_t d2 = 0; d2 < (size_t)dim; ++d2){ + J(d1, bf.node_id(), d2, sh) += diffFlux (d1, d2); + // if ( sh < 2 ) UG_LOG("bf.node_id(): " << bf.node_id() << "sh: " << sh << ": diff_flux added: " << diffFlux (d1, d2) << "\n"); + } + + // 5. Add pressure term to local Jacobian + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + J(d1, bf.node_id(), _P_, sh) -= bf.shape(sh) * bf.normal()[d1]; + + } + +} + +template +void ParticleBndCond:: +add_jac_A_elem_Quadri_for2(LocalMatrix& J, const LocalVector locU) +{ + +// Loop the boundary faces to assemble impulse equations + SmartPtr > fluidDensity = m_spMaster->density(); + std::vector& vBF = m_spInterfaceHandlerLocal->get_boundary_faces(); + + if ( vBF.size() != 4 ) + UG_THROW("in 'ParticleBndCond::add_jac_A_elem_Quadri_for2(): vBF.size() should be 4 but is " << vBF.size() << "\n"); + + +// get density + number importDensity = fluidDensity->value(0, 0); + if ( fluidDensity->value(0, 0) != fluidDensity->value(1, 0) ) + UG_THROW("ParticleBndCond::add_jac_A_elem_Quadri_for2(): density different for series 0 and 1: " + << fluidDensity->value(0, 0) << " = " << fluidDensity->value(1, 0) << "\n"); + if ( importDensity != get_density_fluid() ) + UG_THROW("ParticleBndCond::add_jac_A_elem_Quadri_for2(): importDensity = " << importDensity << " = " + "fluidDensity = " << get_density_fluid() << "\n"); + +// loop all boundary faces + for(size_t ip = 0; ip < vBF.size(); ++ip) + { + interfaceBF bf = vBF[ip]; + + // Momentum equation: + if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling + diffusive_flux_Jac(ip, bf, J, locU); + + + // The continuity equation + if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling + { + for(size_t sh = 0; sh < bf.num_sh(); ++sh) // loop shape functions + for (size_t d2 = 0; d2 < (size_t)dim; ++d2) + J(_P_, bf.node_id(), d2, sh) += bf.shape(sh) * bf.normal()[d2] + * importDensity; + } + + if ( 1 ) + { + UG_LOG("----- ip = " << ip << "------\n"); + UG_LOG("bf.nodeID: " << bf.node_id() << "\n"); + UG_LOG(" bf.normal(): " << bf.normal() << "\n"); + UG_LOG("bf.vGloPos[0: " << bf.global_corner(0) << "\n"); + UG_LOG("bf.vGloPos[1]: " << bf.global_corner(1) << "\n"); + } + } // end vBF-loop + + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 4 ) + { + UG_LOG("J = " << J << "\n"); + UG_LOG("J.num_all_row_dof(0): " << J.num_all_row_dof(0) << "\n"); + } + +} + + +void copy_and_reset(LocalMatrix& cpJ, LocalMatrix& J) +{ + + for(size_t fct1 = 0; fct1 < J.num_all_row_fct(); ++fct1) + for(size_t dof1 = 0; dof1 < J.num_all_row_dof(fct1); ++dof1) + for(size_t fct2 = 0; fct2 < J.num_all_row_fct(); ++fct2) + for(size_t dof2 = 0; dof2 < J.num_all_row_dof(fct2); ++dof2) + { + cpJ(fct1, dof1, fct2, dof2) = J(fct1, dof1, fct2, dof2); + J(fct1, dof1, fct2, dof2) = 0.0; + } +} + +template +size_t ParticleBndCond:: +remap_for2( size_t dof) +{ + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + if ( dof == m_spInterfaceHandlerLocal->m_vNOInterfaceID[0] ) + return 4; + + UG_LOG("m_spInterfaceHandlerLocal->m_vInterfaceID[0]: " << m_spInterfaceHandlerLocal->m_vInterfaceID[0] << "\n"); + UG_LOG("m_spInterfaceHandlerLocal->m_vInterfaceID[1]: " << m_spInterfaceHandlerLocal->m_vInterfaceID[1] << "\n"); + + UG_LOG("m_spInterfaceHandlerLocal->m_vQuadriOrigID[0]: " << m_spInterfaceHandlerLocal->m_vQuadriOrigID[0] << "\n"); + UG_LOG("m_spInterfaceHandlerLocal->m_vQuadriOrigID[2]: " << m_spInterfaceHandlerLocal->m_vQuadriOrigID[2] << "\n"); + + UG_LOG("m_spInterfaceHandlerLocal->m_vNOInterfaceID[0]: " << m_spInterfaceHandlerLocal->m_vNOInterfaceID.size() << "\n"); + + if ( m_spInterfaceHandlerLocal->m_vInterfaceID[0] == m_spInterfaceHandlerLocal->m_vQuadriOrigID[0] ) + { + if ( dof == m_spInterfaceHandlerLocal->m_vInterfaceID[0] ) + return 0; + else if ( dof == m_spInterfaceHandlerLocal->m_vInterfaceID[1] ) + return 2; + else UG_THROW("ParticleBndCond::remap: error1: dof = " << dof << "\n"); + } + else if ( m_spInterfaceHandlerLocal->m_vInterfaceID[0] == m_spInterfaceHandlerLocal->m_vQuadriOrigID[2] ) + { + if ( dof == m_spInterfaceHandlerLocal->m_vInterfaceID[0] ) + return 2; + else if ( dof == m_spInterfaceHandlerLocal->m_vInterfaceID[1] ) + return 0; + else UG_THROW("ParticleBndCond::remap: error2: dof = " << dof << "\n"); + } + else UG_THROW("ParticleBndCond::remap: error3: dof = " << dof << "\n"); + +} + +template +template +void ParticleBndCond:: +add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) +{ + ElementModus elemModus = m_spInterfaceHandlerLocal->get_element_modus(elem); // computed via 'compute_element_modus()' during 'update_marker()' + + //////////////////////////////////////////////////////////////////////////////// + // Remove local impuls equations for interface-corners + if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling + { + + if ( elemModus != INSIDE_DOM ) + { + // all impulse equations will be removed + std::vector vFctID(dim); + for(size_t i = 0; i < dim; ++i) vFctID[i] = i; + + // equations for interface nodes will be removed + std::vector vDoFID; vDoFID.clear(); + for(size_t i = 0; i < m_spInterfaceHandlerLocal->m_vInterfaceID.size(); ++i) + { + size_t interfaceID = m_spInterfaceHandlerLocal->m_vInterfaceID[i]; + size_t indexToRemove = interfaceID; //m_spInterfaceHandlerLocal->m_vOriginalCornerID[interfaceID]; + vDoFID.push_back(indexToRemove); + } + + remove_equations(J, vFctID, vDoFID); + } + + } + + if ( elemModus == CUT_BY_2_INTERFACE && ! m_spInterfaceHandlerLocal->StdFV_assembling() ) + { + + for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vNOInterfaceID.size(); ++i ) + UG_THROW("m_vNOInterfaceID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vNOInterfaceID[i] << "\n"); + for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vInterfaceID.size(); ++i ) + UG_LOG("m_vInterfaceID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vInterfaceID[i] << "\n"); + for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vQuadriOrigID.size(); ++i ) + UG_LOG("m_vQuadriOrigID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vQuadriOrigID[i] << "\n"); + + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + { + size_t copyID = m_spInterfaceHandlerLocal->m_vNOInterfaceID[0]; + const LocalIndices& ind = m_spInterfaceHandlerLocal->get_local_indices(); + LocalMatrix buffJ; buffJ.resize(ind); buffJ = 0; + UG_LOG("1 buffJ = " << buffJ << "\n"); + + copy_and_reset(buffJ,J); + UG_LOG("2 buffJ = " << buffJ << "\n"); + + + // remap impulse equation for inside node + for(size_t j = 0; j < dim; ++j) + for(size_t fct = 0; fct < J.num_all_row_fct(); ++fct) + for(size_t dof = 0; dof < 3; ++dof) + J(j, remap_for2(copyID), fct, remap_for2(dof)) = buffJ(j, copyID, fct, dof); + + + // remap pressure equation for all nodes + for(size_t dof1 = 0; dof1 < 3; ++dof1) + for(size_t fct = 0; fct < J.num_all_row_fct(); ++fct) + for(size_t dof2 = 0; dof2 < 3; ++dof2) + J(_P_, remap_for2(dof1), fct, remap_for2(dof2)) = buffJ(_P_, dof1, fct, dof2); + + + } + + // case == 4: all entries (also for pressure eq) will be written newly, since only boundary faces are relevant + // => during remove_equations() only velocity equations were removed! + + //if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + // remap_inside_equation(J, vFctID, vDoFID); + //else + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 4 ) + J = 0.0; + //else + // UG_THROW("in ParticleBndCond::add_def_A_elem(): wrong amount of interface.size() for CUT_BY_2_INTERFACE: " << m_spInterfaceHandlerLocal->interface_id_all().size() << " ( should be 2!)\n"); + + + const LocalIndices& ind = m_spInterfaceHandlerLocal->get_local_indices(); + LocalVector quadriU; + quadriU.resize(ind); + + write_QuadriSol(quadriU); + + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 4 || m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + add_jac_A_elem_Quadri_for2(J, quadriU); + else + UG_THROW("in ParticleBndCond::add_def_A_elem(): wrong amount of interface.size() for CUT_BY_2_INTERFACE: " << m_spInterfaceHandlerLocal->interface_id_all().size() << " ( should be 2!)\n"); + + if ( 0 ) //m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + UG_THROW("J = \n" << J << "\n"); + + UG_LOG("end CUT_BY_2_INTERFACE\n"); + + return; + } + +//////////////////////////////////////////////////////////////////////////////// +// see 'ParticleFlatTop::add_jac_A_elem_interface()' +//////////////////////////////////////////////////////////////////////////////// + +// Loop the boundary faces for new impuls equations +// --> IFF INSIDE_DOM: vBF.size() = 0 ;-) + SmartPtr > fluidDensity = m_spMaster->density(); + std::vector& vBF = m_spInterfaceHandlerLocal->get_boundary_faces(); + +// initialize data (written during call of 'diffusive_flux_Jac()': + LocalIndices ind = u.get_indices(); + rotJ_ind.resize(ind); rotJ_ind = 0.0; + rotJ_rot.resize(ind); rotJ_rot = 0.0; + + for(size_t ip = 0; ip < vBF.size(); ++ip) + { + + interfaceBF bf = vBF[ip]; + + if ( fluidDensity->value(0, ip) != fluidDensity->value(1, ip) ) + UG_THROW("ParticleBndCond::add_jac_M_elem(): density different for series 0 and 1: " + << fluidDensity->value(0, ip) << " != " << fluidDensity->value(1, ip) << "\n"); + + number importDensity = fluidDensity->value(0, ip); + + // The momentum equation: + if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling + diffusive_flux_Jac(ip, bf, J, u); + // diffusive_flux_Jac_rot(ip, bf, J, u, importDensity); + + // scale with deltaT ( = 1.0 for non-time-dependent) + // buffJ *= deltaT; + // ToDo --> NOT necessary, since add_def_A_elem() will be multiplied by 'dt' + // during elem_dis_assemble_util.h ??? + + // The continuity equation + if ( 1 ) //! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling + { + for(size_t sh = 0; sh < bf.num_sh(); ++sh) // loop shape functions + for (size_t d2 = 0; d2 < (size_t)dim; ++d2) + J(_P_, bf.node_id(), d2, sh) += bf.shape(sh) * bf.normal()[d2] + * importDensity; + } + + } // end vBF + + // copy rotJ_ind/rotJ_rot to m_spInterfaceHandlerLocal data for access from mapper + if ( vBF.size() > 0 ) + copy_local_couplings_jac(); + + +} + + +//////////////////////////////////////////////////////////////////////////////// +// methods for adapting defect due to the bnd cond +//////////////////////////////////////////////////////////////////////////////// + +// removes the defects with IDs in 'vFctID' locally assembled in the corners of 'vDofID' +template +void ParticleBndCond:: +remove_equations(LocalVector& d, std::vector vFctID, std::vector vDofID) +{ + for(size_t i = 0; i < vDofID.size(); ++i) + for(size_t j = 0; j < vFctID.size(); ++j) + d(vFctID[j], vDofID[i]) = 0.0; + +} + +// see 'NavierStokesNoNormalStressOutflowFV1::diffusive_flux_defect()' +template +void ParticleBndCond:: +diffusive_flux_defect_rot(const size_t ip, const interfaceBF& bf, LocalVector& d, const LocalVector& u) +{ + int prtIndex = get_prtIndex(); + + MathVector transSol = m_spInterfaceHandlerLocal->get_transSol(prtIndex, 0); + MathVector rotSol = m_spInterfaceHandlerLocal->get_rotSol(prtIndex, 0); + const MathVector center = m_spInterfaceHandlerLocal->get_center(prtIndex); + + + MathMatrix gradVel; + MathVector diffFlux; + MathVector pressureRot; + + + MathVector RotDef; + MathMatrix rotationMatIP_transposed = m_spInterfaceHandlerLocal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_ip(bf.node_id())); + Transpose(rotationMatIP_transposed); + +// 1. Get the gradient of the velocity at ip + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + for(size_t d2 = 0; d2 < (size_t)dim; ++d2) + { + // sum up contributions of each shape + gradVel(d1, d2) = 0.0; + for(size_t sh = 0; sh < bf.num_sh(); ++sh) + { + if ( m_spInterfaceHandlerLocal->lies_onInterface(sh) ) + { + MathVector radialCo; + VecSubtract(radialCo, m_spInterfaceHandlerLocal->corner(sh), center); + UG_LOG("m_spInterfaceHandlerLocal->corner(sh) = " << m_spInterfaceHandlerLocal->corner(sh) << "\n"); + MathMatrix rotationMatCo = m_spInterfaceHandlerLocal->get_rotationMat(radialCo); + // set solution + number sol = transSol[d1]; + for ( int d = 0; d < dim; ++d ) + sol += rotationMatCo[d1][d]*rotSol[d]; + + gradVel(d1, d2) += bf.global_grad(sh)[d2] * sol; + } + else + gradVel(d1, d2) += bf.global_grad(sh)[d2] * u(d1, sh); + } + } + + +// 2. Compute the total flux +// - add (\nabla u) \cdot \vec{n} + MatVecMult(diffFlux, gradVel, bf.normal()); + +// - add (\nabla u)^T \cdot \vec{n} + if( !m_spMaster->laplace()) + TransposedMatVecMultAdd(diffFlux, gradVel, bf.normal()); + +// 3. Scale by viscosity + diffFlux *= get_kinVisc_fluid(); + +// 4. compute r x [\sigma(u)] + MatVecMult(RotDef, rotationMatIP_transposed, diffFlux); + +// 5. Change sign, since force acts onto particle in inverse direction: + //diffFlux *= -1.0; + +// 6. Add flux to local defect + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + { + d(d1, bf.node_id()) += diffFlux[d1]; + rotD(d1, bf.node_id()) += RotDef[d1]; + } + +// 7. Add pressure term to local defect + number pressure = 0.0; + for(size_t sh = 0; sh < bf.num_sh(); ++sh) + pressure += bf.shape(sh) * u(_P_, sh); + + MatVecMult(pressureRot, rotationMatIP_transposed, bf.normal()); + if ( fabs(pressureRot[0]) > 1e-10 ) + UG_THROW("pressureRot " << pressureRot << "\n"); + + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + { + d(d1, bf.node_id()) -= pressure * bf.normal()[d1]; + rotD(d1, bf.node_id()) -= pressure * pressureRot[d1]; + + } +} + + +// see 'NavierStokesNoNormalStressOutflowFV1::diffusive_flux_defect()' +template +void ParticleBndCond:: +diffusive_flux_defect(const size_t ip, const interfaceBF& bf, LocalVector& d, const LocalVector& u) +{ + MathMatrix gradVel; + MathVector diffFlux; + +// 1. Get the gradient of the velocity at ip + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + for(size_t d2 = 0; d2 < (size_t)dim; ++d2) + { + // sum up contributions of each shape + gradVel(d1, d2) = 0.0; + for(size_t sh = 0; sh < bf.num_sh(); ++sh) + gradVel(d1, d2) += bf.global_grad(sh)[d2] * u(d1, sh); + } + +// 2. Compute the total flux + +// - add (\nabla u) \cdot \vec{n} + MatVecMult(diffFlux, gradVel, bf.normal()); + +// - add (\nabla u)^T \cdot \vec{n} + if( !m_spMaster->laplace()) + TransposedMatVecMultAdd(diffFlux, gradVel, bf.normal()); + +// 3. Scale by viscosity + diffFlux *= get_kinVisc_fluid(); + +// 4. Change sign, since force acts onto particle in inverse direction: + //diffFlux *= -1.0; + +// 5. Add flux to local defect + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + d(d1, bf.node_id()) += diffFlux[d1]; + + +// 6. Add pressure term to local defect + number pressure = 0.0; + for(size_t sh = 0; sh < bf.num_sh(); ++sh) + pressure += bf.shape(sh) * u(_P_, sh); + + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + d(d1, bf.node_id()) -= pressure * bf.normal()[d1]; + +} + +template +void ParticleBndCond:: +add_def_A_elem_Quadri_for2(LocalVector& locD, const LocalVector locU) +{ +// Loop the boundary faces to assemble impulse equations + SmartPtr > fluidDensity = m_spMaster->density(); + std::vector& vBF = m_spInterfaceHandlerLocal->get_boundary_faces(); + + if ( vBF.size() != 4 ) + UG_THROW("in 'ParticleBndCond::add_def_A_elem_Quadri_for2(): vBF.size() should be 4 but is " << vBF.size() << "\n"); + + UG_LOG("vBF.size(): " << vBF.size() << "\n"); + +// get density + number importDensity = fluidDensity->value(0, 0); + if ( fluidDensity->value(0, 0) != fluidDensity->value(1, 0) ) + UG_THROW("ParticleBndCond::add_def_A_elem_Quadri_for2(): density different for series 0 and 1: " + << fluidDensity->value(0, 0) << " != " << fluidDensity->value(1, 0) << "\n"); + if ( importDensity != get_density_fluid() ) + UG_THROW("ParticleBndCond::add_def_A_elem_Quadri_for2(): importDensity = " << importDensity << " = " + "fluidDensity = " << get_density_fluid() << "\n"); + +// loop all boundary faces + for(size_t ip = 0; ip < vBF.size(); ++ip) + { + UG_LOG("---- ip = " << ip << "\n"); + + interfaceBF bf = vBF[ip]; + + // Compute Velocity at ip + MathVector stdVel(0.0); + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + for(size_t sh = 0; sh < bf.num_sh(); ++sh) + stdVel[d1] += locU(d1, sh) * bf.shape(sh); + + // Momentum equation: + if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling + diffusive_flux_defect(ip, bf, locD, locU); + + // Continuity equation: + if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling + locD(_P_, bf.node_id()) += VecDot(stdVel, bf.normal()) * importDensity; + + } // end vBF-loop + +} + +template +void ParticleBndCond:: +write_QuadriSol(const LocalVector origU) +{ + UG_LOG("start write_QuadriSol\n"); + +// initialize data + LocalIndices ind = origU.get_indices(); + LocalVector quadriU; + + UG_LOG("1 start write_QuadriSol\n"); + + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + { + for(size_t fct = 0; fct < ind.num_fct(); ++fct) + ind.resize_dof(fct, 5); + + if ( ind.num_dof(0) != 5 ) + UG_THROW("hmm: ind.num_dof(0) = " << ind.num_dof(0) << "\n"); + } + quadriU.resize(ind); + + UG_LOG("2 start write_QuadriSol\n"); + + // A. remap solution (velocity AND pressure!) of inside node + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + { + size_t copyID = m_spInterfaceHandlerLocal->m_vNOInterfaceID[0]; + for(size_t fct = 0; fct < dim+1; ++fct) + {quadriU(fct,4) = origU(fct,copyID); + UG_LOG("origU(fct,copyID) = " << origU(fct,copyID) << "\n");} + } + + UG_LOG("3 start write_QuadriSol: quadriU \n" << quadriU << "\n"); + + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + { + for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vNOInterfaceID.size(); ++i ) + UG_THROW("m_vNOInterfaceID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vNOInterfaceID[i] << "\n"); + + } + for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vInterfaceID.size(); ++i ) + UG_LOG("m_vInterfaceID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vInterfaceID[i] << "\n"); + for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vQuadriOrigID.size(); ++i ) + UG_LOG("m_vQuadriOrigID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vQuadriOrigID[i] << "\n"); + + std::vector testV; + for(size_t dof = 0; dof < 4; ++dof) + testV.push_back(1.0+0.1*dof); + + // B. remap pressure solution in all interface nodes + for(size_t fct = 0; fct < dim+1; ++fct) + for(size_t dof = 0; dof < 4; ++dof) + { + quadriU(fct,dof) = testV[m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]]; //origU(fct,m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]); + UG_LOG("quadriU(fct,dof): " << quadriU(fct,dof) << "\n"); + UG_LOG("testV[" << m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof] << "]: " << testV[m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]] << "\n"); + } + + UG_LOG("start write_QuadriSol: quadriU = \n" << quadriU << "\n"); + UG_THROW("4 start write_QuadriSol\n"); + +// C. write velocities of the 2 particles: + MathVector transSol1 = m_spInterfaceHandlerLocal->get_transSol(0, 0); + MathVector rotSol1 = m_spInterfaceHandlerLocal->get_rotSol(0, 0); + MathVector transSol2 = m_spInterfaceHandlerLocal->get_transSol(1, 0); + MathVector rotSol2 = m_spInterfaceHandlerLocal->get_rotSol(1, 0); + + UG_LOG("transSol1 = " << transSol1 << "\n"); + UG_LOG("transSol2 = " << transSol2 << "\n"); + UG_LOG("rotSol1 = " << rotSol1 << "\n"); + UG_LOG("rotSol2 = " << rotSol2 << "\n"); + +// resize local data as done during 'modify_LocalSol' +// --> but there with num_co = 3 for the Triangle with inside node! + for(size_t fct = 0; fct < ind.num_fct(); ++fct) + for(size_t dof = 0; dof < 4; ++dof) + { + MathMatrix rotationMatCo = m_spInterfaceHandlerLocal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(dof)); + UG_LOG("write_QuadriSol: radial(" << dof << ": " << m_spInterfaceHandlerLocal->radial_at_co(dof) << "\n"); + + // write solution of particle with prtIndex = 0: + if ( dof < 2 ) + { + quadriU(fct,dof) = transSol1[fct]; + for ( int d = 0; d < dim; ++d ) + quadriU(fct,dof) += rotationMatCo[fct][d]*rotSol1[d]; + } + // write solution of particle with prtIndex = 1: + else + { + quadriU(fct,dof) = transSol2[fct]; + for ( int d = 0; d < dim; ++d ) + quadriU(fct,dof) += rotationMatCo[fct][d]*rotSol2[d]; + } + } + + + UG_LOG("after write_QuadriSol: quadriU = \n" << quadriU << "\n"); + +} + +template +void ParticleBndCond:: +add_quadri_to_defect(LocalVector& d, const LocalVector& quadriD) +{ +// const LocalIndices& ind = quadriD.get_indices(); + UG_LOG("START add_quadri_to_defect \n"); + + for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vQuadriOrigID.size(); ++i ) + UG_LOG("m_vOrig[" << i << "] = " << m_spInterfaceHandlerLocal->m_vQuadriOrigID[i] << "\n"); + + UG_LOG("d: \n" << d << "\n"); + UG_LOG("quadriD: \n" << quadriD << "\n"); + for(size_t fct=0; fct < quadriD.num_all_fct(); ++fct) + { + UG_LOG("fct = " << fct << "quadriD.num_all_dof(fct) = " << quadriD.num_all_dof(fct) << "\n"); + + for(size_t dof=0; dof < quadriD.num_all_dof(fct); ++dof) + { + UG_LOG("0 -> dof = " << dof << "\n"); + + if ( quadriD.value(fct,dof) != quadriD.value(fct,dof)) + UG_THROW("NAN in 'add_quadri_to_defect()'!...\n"); + + bool isPrtNode = m_spInterfaceHandlerLocal->lies_onInterface(dof); + // usual assembling for fluid-dof and pressure-fct + if ( isPrtNode ) + { + size_t _dof = m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]; + UG_LOG("dof = " << dof << ", _dof = " << _dof << "\n"); + + d.value(fct,_dof) += quadriD.value(fct,dof); + UG_LOG("d = \n" << d << "\n"); + + } + + } + } + +} + + + +template +template +void ParticleBndCond:: +add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) +{ +//////////////////////////////////////////////////////////////////////////////// +// Remove local impulse equations for interface-corners + + ElementModus elemModus = m_spInterfaceHandlerLocal->get_element_modus(elem); // computed via 'compute_element_modus()' during 'update_marker()' + if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling + { + if ( elemModus != INSIDE_DOM ) + { + // all impulse equations will be removed + std::vector vFctID(dim); + for(size_t i = 0; i < dim; ++i) vFctID[i] = i; + + // equations for interface nodes will be removed + std::vector vDoFID; vDoFID.clear(); + for(size_t i = 0; i < m_spInterfaceHandlerLocal->m_vInterfaceID.size(); ++i) + { + size_t interfaceID = m_spInterfaceHandlerLocal->m_vInterfaceID[i]; + size_t indexToRemove = interfaceID; //m_spInterfaceHandlerLocal->m_vOriginalCornerID[interfaceID]; + vDoFID.push_back(indexToRemove); + } + + remove_equations(d, vFctID, vDoFID); + + } + } + + + if ( elemModus == CUT_BY_2_INTERFACE && !m_spInterfaceHandlerLocal->StdFV_assembling()) + { + write_QuadriSol(u); + + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + + // case == 4: all entries (also for pressure eq) will be written newly, since only boundary faces are relevant + // => during remove_equations() only velocity equations were removed! + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 4 ) + d = 0.0; + + // locU was written during 'ParticleMapper::modify_LocalData()': + if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 4 || m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + add_def_A_elem_Quadri_for2(d, u); + else + UG_THROW("in ParticleBndCond::add_def_A_elem(): wrong amount of interface.size() for CUT_BY_2_INTERFACE: " << m_spInterfaceHandlerLocal->interface_id_all().size() << " ( should be 2!)\n"); + + return; + } + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +// initialize data (written during call of 'diffusive_flux_Jac()': + LocalIndices ind = u.get_indices(); + rotD.resize(ind); rotD = 0.0; + + + // ToDo: if ( CUT_BY_2 && m_spInterfaceHandlerLocal->m_vInterfaceID.size() == 2 ) + // => TRIANGLE/5-Eck! => write u( , ) neu!! + +// Loop the boundary faces to assemble impulse equations + SmartPtr > fluidDensity = m_spMaster->density(); + std::vector& vBF = m_spInterfaceHandlerLocal->get_boundary_faces(); + + + if ( dim == 2 && vBF.size() > 2 ) + UG_THROW("add_def_A_elem(): vBF.size() is greater than 2: " << vBF.size() << "\n"); + + for(size_t ip = 0; ip < vBF.size(); ++ip) + { + interfaceBF bf = vBF[ip]; + + // Compute Velocity at ip + MathVector stdVel(0.0); + for(size_t d1 = 0; d1 < (size_t)dim; ++d1) + for(size_t sh = 0; sh < bf.num_sh(); ++sh) + stdVel[d1] += u(d1, sh) * bf.shape(sh); + + // Momentum equation: + if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling + diffusive_flux_defect(ip, bf, d, u); + + // scale with deltaT ( = 1.0 for non-time-dependent) + // d *= deltaT; + // ToDo --> NOT necessary, since add_def_A_elem() will be multiplied by 'dt' + // during elem_dis_assemble_util.h ??? + + if ( fluidDensity->value(0, ip) != fluidDensity->value(1, ip) ) + UG_THROW("ParticleBndCond::add_jac_M_elem(): density different for series 0 and 1: " + << fluidDensity->value(0, ip) << " != " << fluidDensity->value(1, ip) << "\n"); + number importDensity = fluidDensity->value(0, ip); + if ( importDensity != get_density_fluid() ) + UG_THROW("ParticleBndCond::add_def_A_elem(): importDensity = " << importDensity << " != " + "fluidDensity = " << get_density_fluid() << "\n"); + + + // Continuity equation: + if ( 1 ) //! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling + d(_P_, bf.node_id()) += VecDot(stdVel, bf.normal()) * importDensity; + // ToDo m_massDefect += VecDot(stdVel, bf.normal()); + } + +/* if ( elemModus == CUT_BY_INTERFACE ) + if ( m_spInterfaceHandlerLocal->m_vInterfaceID.size() == 2 ) + UG_THROW("vBF.size() = " << vBF.size() << "\n"); +*/ + // copy rotJ_ind/rotJ_rot to m_spInterfaceHandlerLocal data for access from mapper + + copy_local_couplings_def(); + + +} +//////////////////////////////////////////////////////////////////////////////// +// methods for adapting mass matrix for bnd cond +//////////////////////////////////////////////////////////////////////////////// + +// instead of calling 'set_mass_and_inertia()' during 'add_local_mat_to_global_interface()' +template +template +void ParticleBndCond:: +add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) +{ + ElementModus modus = m_spInterfaceHandlerLocal->elementModus(); + +// A. do nothing for inside elements + if ( modus == INSIDE_DOM ) + return; + +// B. for outside elements: geo.num_scv() = 0 +// => nothing added during NavierStokesFV1::add_jac_M_elem +// => nothing will be subtracted here :) + + +/////////////////////////////////////////////////////////////////////////////// +// substract part added by NavierStokesFV1::add_jac_M_elem(): +// (instead of setting scv.volume() to zero) +//////////////////////////////////////////////////////////////////////////////// + +// Only first order implementation + UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); + +// get finite volume geometry + static TFVGeom& geo = GeomProvider::get(LFEID(LFEID::LAGRANGE, dim, 1), 1); + + SmartPtr > fluidDensity = m_spMaster->density(); + +// loop Sub Control Volumes (SCV) + for(size_t ip = 0; ip < geo.num_scv(); ++ip) + { + // get SCV + const typename TFVGeom::SCV& scv = geo.scv(ip); + + // get associated node + const int sh = scv.node_id(); + + if ( !m_spInterfaceHandlerLocal->lies_onInterface(sh) ) + continue; + + if ( fluidDensity->value(0, ip) != fluidDensity->value(1, ip) ) + UG_THROW("ParticleBndCond::add_jac_M_elem(): density different for series 0 and 1: " + << fluidDensity->value(0, ip) << " != " << fluidDensity->value(1, ip) << "\n"); + + number importDensity = fluidDensity->value(0, ip); + + // loop velocity components + for(int d1 = 0; d1 < dim; ++d1) + { + // Add to local matrix + J(d1, sh, d1, sh) -= scv.volume() * importDensity; + } + } + + return; + + + const int prtIndex = get_prtIndex(); + const number prtDensity = get_density(prtIndex); + +// if INSIDE_DOM: do nothing! + if ( modus != INSIDE_DOM ) + { + // get data + const ReferenceObjectID roid = elem->reference_object_id(); + const DimReferenceElement& rRefElem + = ReferenceElementProvider::get(roid); + + // OUTSIDE_DOM + if ( modus == OUTSIDE_DOM ) + { + // loop corners of reference element + for(size_t sh = 0; sh < rRefElem.num(0); ++sh) + { + // loop velocity components + for(int d1 = 0; d1 < dim; ++d1) + { + // Add to local matrix + J(d1, sh, d1, sh) += geo.volume_fem_elem() * prtDensity; + // rescale volume fraction + J(d1, sh, d1, sh) *= 1.0/rRefElem.num(0); + } + } + } + // CUT_BY_INTERFACE + else if ( modus == CUT_BY_INTERFACE ) + { + // loop corners of reference element + for(size_t sh = 0; sh < rRefElem.num(0); ++sh) + { + // loop velocity components + for(int d1 = 0; d1 < dim; ++d1) + { + // Add to local matrix + J(d1, sh, d1, sh) += geo.volume_fem_elem() * prtDensity; + UG_THROW("geo.volume_fem_elem() = " << geo.volume_fem_elem() << "\n"); + // rescale volume fraction + J(d1, sh, d1, sh) *= 1.0/rRefElem.num(0); + } + } + } + else + UG_THROW("ParticleBndCond::add_jac_M_elem()..."); + + } // end 'if ( !is_inside_elem() )' + + +} + + +template +template +void ParticleBndCond:: +add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) +{ + ElementModus modus = m_spInterfaceHandlerLocal->elementModus(); + +// A. do nothing for inside elements + if ( modus == INSIDE_DOM ) + return; + +// B. for outside elements: geo.num_scv() = 0 +// => nothing added during NavierStokesFV1::add_jac_M_elem +// => nothing will be subtracted here :) + + +/////////////////////////////////////////////////////////////////////////////// +// substract part added by NavierStokesFV1::add_jac_M_elem(): +// (instead of setting scv.volume() to zero) +//////////////////////////////////////////////////////////////////////////////// + +// Only first order implementation + UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); + +// get finite volume geometry + static TFVGeom& geo = GeomProvider::get(LFEID(LFEID::LAGRANGE, dim, 1), 1); + + SmartPtr > fluidDensity = m_spMaster->density(); + +// loop Sub Control Volumes (SCV) + for(size_t ip = 0; ip < geo.num_scv(); ++ip) + { + // get current SCV + const typename TFVGeom::SCV& scv = geo.scv(ip); + + // get associated node + const int sh = scv.node_id(); + + if ( !m_spInterfaceHandlerLocal->lies_onInterface(sh) ) + continue; + + if ( fluidDensity->value(0, ip) != fluidDensity->value(1, ip) ) + UG_THROW("ParticleBndCond::add_jac_M_elem(): density different for series 0 and 1: " + << fluidDensity->value(0, ip) << " != " << fluidDensity->value(1, ip) << "\n"); + + number importDensity = fluidDensity->value(0, ip); + + // loop velocity components + for(int d1 = 0; d1 < dim; ++d1) + { + // Add to local matrix + d(d1, sh) -= u(d1, sh) * scv.volume() * importDensity; + } + } + + +} + +//////////////////////////////////////////////////////////////////////////////// +/// methods for adapting the rhs due to the bnd cond +//////////////////////////////////////////////////////////////////////////////// + +// here gravity force -> independent of velocity solution! +template +template +void ParticleBndCond:: +add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoords[]) +{ + return; + + + ElementModus modus = m_spInterfaceHandlerLocal->elementModus(); + +// A. do nothing for inside elements + if ( modus == INSIDE_DOM ) + return; + +// B. for outside elements: geo.num_scv() = 0 +// => nothing added during NavierStokesFV1::add_jac_M_elem +// => nothing will be subtracted here :) + + +/////////////////////////////////////////////////////////////////////////////// +// substract part added by NavierStokesFV1::add_rgh_elem(): +// (instead of setting scv.volume() to zero) +//////////////////////////////////////////////////////////////////////////////// + +// Only first order implementation + UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); + +// get finite volume geometry + static TFVGeom& geo = GeomProvider::get(LFEID(LFEID::LAGRANGE, dim, 1), 1); + +// loop Sub Control Volumes (SCV) + for(size_t ip = 0; ip < geo.num_scv(); ++ip) + { + // get current SCV + const typename TFVGeom::SCV& scv = geo.scv(ip); + + // get associated node + const int sh = scv.node_id(); + + if ( !m_spInterfaceHandlerLocal->lies_onInterface(sh) ) + continue; + + // Add to local matrix + d(0, sh) -= scv.volume() * (-9.81); + + } + + + /* + +REMARK: funktioniert so nicht, da + 'elem->num_vertices()' nicht existiert fuer 'GridObject* elem' :-(... + + => weiterhin 'set_gravity()' in 'local_to_global' verwenden + +// only assembling for single marked element, containing the transVel-DoF + if ( !m_spInterfaceHandlerLocal->m_spParticleHandlerGlobal->m_spTransVelMarker->is_marked(elem) ) + return; + + UG_LOG("------------------------------------------------------------- add_rhs_elem assembling...\n"); + +// A. get location of DoF of translational velocity + size_t transDoF; + for(size_t dof = 0; dof < elem->num_vertices(); ++dof) + if ( m_spInterfaceHandlerLocal->m_spParticleHandlerGlobal->m_spTransVelMarker->is_marked(elem->vertex(dof)) ) + transDoF = dof; + +// B. get corresponding DoFIndex + const size_t fct_gravity = 0; + const LocalIndices& ind = d.get_indices(); + const DoFIndex transInd = DoFIndex(ind.index(fct_gravity,transDoF), ind.comp(fct_gravity,transDoF)); + +// C. compute gravitational force + bool logGravity = true; + + if ( logGravity ) UG_LOG("//////////////////////////////// - log_Gravity - ///////////////////////////////\n"); + if ( logGravity ) UG_LOG("*VORHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); + if ( logGravity ) UG_LOG("*VORHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); + if ( logGravity ) UG_LOG("*VORHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); + if ( logGravity ) UG_LOG("*VORHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); + + const int prtIndex = get_prtIndex(); + const number radius = m_spInterfaceHandlerLocal->m_spParticleHandlerGlobal->get_radius(prtIndex); + number volume; // = Volume(Index,p); // VORSICHT! -> gmg divergiert fuer diese Version: volume = 3.1415*radius*radius; + if ( dim == 2 ) + volume = 3.1415*radius*radius; + if ( dim == 3 ) + volume = 4/3*3.1415*radius*radius*radius; + const number gravitationalMass = volume*1.0; //m_DensityPrt[prtIndex]; //m_EffectiveDensityPrt[p]; + const number gravityForce = -9.81*gravitationalMass; + + if ( logGravity ) UG_LOG ("*radius: " << radius << "\n"); + if ( logGravity ) UG_LOG ("*volume: " << volume << "\n"); + if ( logGravity ) UG_LOG ("*prtIndex: " << prtIndex << "\n"); + + if ( logGravity ) UG_LOG ("*gravForce added: " << gravityForce << "timeFactor: " << timeFactor <<"\n"); + if ( logGravity ) UG_LOG("//////////////////////////////// - log_Gravity - ///////////////////////////////\n"); + if ( logGravity ) UG_LOG("*NACHHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); + if ( logGravity ) UG_LOG("*NACCHHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); + if ( logGravity ) UG_LOG("*NACHHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); + if ( logGravity ) UG_LOG("*NACHHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); + +// D. add gravitational force to rhs + DoFRef(d, transInd) -= gravityForce; + +*/ +} + + + +//////////////////////////////////////////////////////////////////////////////// +// register assemble functions +//////////////////////////////////////////////////////////////////////////////// + +#ifdef UG_DIM_1 +template<> +void ParticleBndCond:: +register_all(bool bHang) +{ +// switch assemble functions + if(!bHang) + { + register_func > >(); + +// register_func >(); + } + else + { + UG_THROW("ParticleBndCond: Hanging Nodes not implemented.") + } +} +#endif + +#ifdef UG_DIM_2 +template<> +void ParticleBndCond:: +register_all(bool bHang) +{ +// switch assemble functions + if(!bHang) + { + register_func > >(); +/* + register_func >(); + register_func >(); + */ + } + else + { + UG_THROW("ParticleBndCond: Hanging Nodes not implemented.") + } +} +#endif + +#ifdef UG_DIM_3 +template<> +void ParticleBndCond:: +register_all(bool bHang) +{ +// switch assemble functions + if(!bHang) + { + register_func > >(); +/* + register_func >(); + register_func >(); + register_func >(); + register_func >(); + */ + } + else + { + UG_THROW("ParticleBndCond: Hanging Nodes not implemented.") + } +} +#endif + +template +template +void +ParticleBndCond:: +register_func() +{ + ReferenceObjectID id = geometry_traits::REFERENCE_OBJECT_ID; + typedef ParticleBndCond T; + + this->clear_add_fct(id); + this->set_prep_elem_loop_fct( id, &T::template prep_elem_loop); + this->set_prep_elem_fct( id, &T::template prep_elem); + this->set_fsh_elem_loop_fct( id, &T::template fsh_elem_loop); + this->set_add_jac_A_elem_fct( id, &T::template add_jac_A_elem); + this->set_add_jac_M_elem_fct( id, &T::template add_jac_M_elem); + this->set_add_def_A_elem_fct( id, &T::template add_def_A_elem); + this->set_add_def_M_elem_fct( id, &T::template add_def_M_elem); + this->set_add_rhs_elem_fct( id, &T::template add_rhs_elem); +} + + +//////////////////////////////////////////////////////////////////////////////// +// explicit template instantiations +//////////////////////////////////////////////////////////////////////////////// + +#ifdef UG_DIM_1 +template class ParticleBndCond; +#endif +#ifdef UG_DIM_2 +template class ParticleBndCond; +#endif +#ifdef UG_DIM_3 +template class ParticleBndCond; +#endif + + +} // end namespace NavierStokes +} // end namespace ug + + +#endif /* PARTICLE_BND_COND_IMPL_H_ */ diff --git a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h new file mode 100644 index 0000000..a020ca7 --- /dev/null +++ b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h @@ -0,0 +1,305 @@ +/* + * moving_particle.h + * + * Created on: 20.01.2015 + * Author: suze + */ + +#ifndef PARTICLE_MAPPER_H_ +#define PARTICLE_MAPPER_H_ + + +#ifdef UG_PARALLEL + #include "lib_grid/parallelization/load_balancer_util.h" +#endif + +#include "lib_disc/spatial_disc/immersed_util/immersed_interface_base.h" + +namespace ug{ +namespace NavierStokes{ + + + +template +class ParticleMapper : public IInterfaceMapper +{ + public: + /// World dimension + static const int dim = TDomain::dim; + + /// abbreviation for pressure + static const size_t _P_ = dim; + + /// Algebra type + typedef TAlgebra algebra_type; + + /// Type of algebra matrix + typedef typename algebra_type::matrix_type matrix_type; + + /// Type of algebra vector + typedef typename algebra_type::vector_type vector_type; + + /// Type of geometric base object + typedef typename domain_traits::grid_base_object grid_base_object; + + /// used boundary face type + typedef typename DimFV1FTGeometry >::BF interfaceBF; + + public: + /// call base class constructor + ParticleMapper(SmartPtr > localHandler) + : m_spInterfaceHandlerLocal(localHandler), + m_spParticleHandlerGlobal(m_spInterfaceHandlerLocal->get_cutElementHandler()), + m_gravityConst(0.0), m_bGravity(true), + m_dt(0.0), m_bTimeDep(false), + m_volume(0.0), m_bVolumeCompExact(true), + m_bUsualAss(false), m_meanDiameter(0.0), + m_bRepulsiveForce(false), + m_bGlowRepulsiveForce(false), + m_bMinimumCorrectionForce(false), + m_repulsiveDistance(0.0), m_rho(0.0), + m_repulsiveForce(0.0), m_epsilon(0.0), + m_bForceLog(false) + + { + // init boolian arrays for all registered particles + size_t numPrt = num_particles(); + m_bFlagGravity.resize(numPrt, false); + m_bFlagInertial.resize(numPrt, false); +// particleValues.data.resize(numPrt); + }; + + /// destructor + ~ParticleMapper() {}; + + /////////////////////////////////////////////////////////////////////////////// + /// + /// base class methods and helper methods called by them + /// + /////////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////////// + /// A. local vector to global + + /// send local entries to global vector + virtual void add_local_vec_to_global(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd); + virtual void add_local_vec_to_global_interface(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd); + virtual void add_local_vec_to_global_interface_for2(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd); + + void adjust_mat_global(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd){}; + + void add_mass_part_def(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); + void add_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); + void set_gravitational_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); + void add_repulsive_force_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); + void add_glowinski_repulsive_force_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); + void add_minimum_correction_force_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); + + void map_all_local_vec_to_transDoF(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd); + virtual void add_local_vec_to_global_FT(vector_type& vec, const LocalVector& lvec, std::vector transInd, std::vector rotInd); + virtual void add_local_vec_to_global_FT_for2_StdFV(vector_type& vec, const LocalVector& lvec, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2); + virtual void add_local_vec_to_global_FT_for2(vector_type& vec, const LocalVector& lvec, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2); + /// helper function for 'add_local_vec_to_global_FT_for2()': + size_t map_for2(size_t dof); + + /// called during 'add_local_vec_to_global_FT_for2()': + void assemble_fluid_nodes(vector_type& vec, const LocalVector& lvec); + + /// called during 'add_local_vec_to_global_FT_for2()': + void assemble_QuadriCorners(vector_type& vec, const LocalVector& lvec, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2); + + /////////////////////////////////////////////////////////////////////////////// + /// B. local matrix to global + + /// send local entries to global rhs + virtual void add_local_mat_to_global(matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd); + virtual void add_local_mat_to_global_interface(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd); + virtual void add_local_mat_to_global_interface_for2(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd); + + void add_mass_part_jac(matrix_type& mat, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); + void map_all_local_mat_to_transDoF(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd); + virtual void add_local_mat_to_global_FT(matrix_type& mat, const LocalMatrix& lmat, + std::vector transInd, std::vector rotInd); + virtual void add_local_mat_to_global_FT_for2_StdFV(matrix_type& mat, const LocalMatrix& lmat, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2); + virtual void add_local_mat_to_global_FT_for2(matrix_type& mat, const LocalMatrix& lmat, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2); + + /// instead of calling base class method 'set_identity_mat()': + /// -> IFF element does NOT include transInd/rotInd-node! + void set_identity_mat_constraint(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd); + + /////////////////////////////////////////////////////////////////////////////// + /// REMARK: + /// During DomainDiscretization::assemble_jacobian: + /// calling + /// ---> m_spAssTuner->modify_LocalData(pModifyMemory, vSol, dd); + /////////////////////////////////////////////////////////////////////////////// + + /// modifies local solution vector for adapted defect computation + virtual void modify_LocalData(LocalMatrix& locJ, LocalVector& locU, ConstSmartPtr dd); + virtual void modify_LocalData(LocalVectorTimeSeries& uT, LocalMatrix& locJ, LocalVector& locU, ConstSmartPtr dd); + + virtual void modify_LocalData(LocalVector& locD, LocalVector& tmpLocD, LocalVector& locU, ConstSmartPtr dd); + virtual void modify_LocalData(LocalVectorTimeSeries& uT, LocalVector& locD, LocalVector& tmpLocD, LocalVector& locU, + ConstSmartPtr dd, size_t t); + + /// method called during 'modify_LocalData()' to set local sol for CUT_BY_2_INTERFACE + void set_QuadriSol(LocalVector& locU, LocalVector& locD); + + /// called during 'modify_LocalData(locU)' + void map_local_data(LocalVector& d); + + /// called during modify_LocalData() for resizing: + void resize_local_indices(LocalVector& locU) + { m_spInterfaceHandlerLocal->resize_local_indices(locU); } + void resize_local_indices(LocalVector& locU, size_t numCo) + { m_spInterfaceHandlerLocal->resize_local_indices(locU, numCo); } + + /// calls m_spParticleHandlerGlobal->set_extraSolTrans/Rot + /// called during 'modify_GlobalSol' + void set_extraSol(vector_type& vec, std::vector transInd, std::vector rotInd, const int timeIndex, const int prtIndex); + + /////////////////////////////////////////////////////////////////////////////// + /// REMARK: + /// During DomainDiscretization::assemble_jacobian: + /// calling + /// ---> m_spAssTuner->modify_GlobalSol(pModifyMemory, vSol, dd); + /// instead of calling + /// ----> m_vConstraint[i]->modify_solution(pModifyMemory, vSol, dd); + /////////////////////////////////////////////////////////////////////////////// + + /// modifies local solution vector for adapted defect computation + virtual void modify_GlobalSol(vector_type& uMod, const vector_type& u, ConstSmartPtr dd); + + virtual void modify_GlobalSol(SmartPtr > vSolMod, + ConstSmartPtr > vSol, ConstSmartPtr dd); + + /////////////////////////////////////////////////////////////////////////////// + /// Further helper methods: + /////////////////////////////////////////////////////////////////////////////// + + int getPrtIndex(size_t dof){ return m_spInterfaceHandlerLocal->getPrtIndex(dof);} + int getMappingModus(size_t fct1, size_t dof1, size_t fct2, size_t dof2); + int getMappingModus_for2(size_t fct1, size_t dof1, size_t fct2, size_t dof2); + int get_prtIndex() { return this->m_spInterfaceHandlerLocal->get_prtIndex(); } + size_t num_particles() const { return m_spParticleHandlerGlobal->num_particles();} + bool UsualAss() { return m_bUsualAss; } + + void set_bUsualAss(bool UsualAss) { m_bUsualAss = UsualAss; } + + void set_gravity(bool gravity, number gravityConst) { m_bGravity = gravity; m_gravityConst = gravityConst;} + void set_repulsive_force(bool repulsive, number forceValue) {m_bRepulsiveForce = repulsive; m_repulsiveForce = forceValue;} + void set_glowinski_repulsive_force(bool repulsive, number rho, number epsilon) {m_bGlowRepulsiveForce = repulsive; m_rho = rho; m_epsilon = epsilon;} + void set_minimum_correction_force(bool repulsive, number equiDist) {m_bMinimumCorrectionForce = repulsive; m_repulsiveDistance = equiDist;} + + void set_volume_comp_mode(bool bVolumeCompMode) { m_bVolumeCompExact = bVolumeCompMode;} + + bool gravitation_force() { return m_bGravity; } + + void set_time_step(number dt) { m_dt = dt; set_time_dependent(true);} + + void set_time_dependent(bool bTimeDep) { m_bTimeDep = bTimeDep; } + bool is_time_dependent() { return m_bTimeDep;} + + void set_element_diameter(double diameter){m_meanDiameter = diameter;UG_LOG("Mean element diameter is " << m_meanDiameter);} + + number get_time_step() + { if ( !is_time_dependent() ) UG_THROW("Call for time step, BUT: not timedependent computation!\n"); + return m_dt; } + + // access methods for '..._FT()': + number get_rotJ_ind(size_t fct1, size_t dof1, size_t fct2, size_t dof2) + { return m_spInterfaceHandlerLocal->get_rotJ_ind(fct1, dof1, fct2, dof2); } + number get_rotJ_rot(size_t fct1, size_t dof1, size_t fct2, size_t dof2) + { return m_spInterfaceHandlerLocal->get_rotJ_rot(fct1, dof1, fct2, dof2); } + + number get_rotD(size_t fct, size_t dof) + { return m_spInterfaceHandlerLocal->get_rotD(fct, dof); } + + int get_Index(const GridLevel& gridLevel, ConstSmartPtr dd) + { return m_spParticleHandlerGlobal->get_Index(gridLevel, dd); } + + void reset_volume(){m_volume = 0.0;} + + number Volume(int levIndex, size_t prtIndex) + { return m_spParticleHandlerGlobal->Volume(levIndex, prtIndex); } + number Mass(const int levIndex, const int prtIndex) + { return m_spParticleHandlerGlobal->Mass(levIndex, prtIndex, m_spInterfaceHandlerLocal->get_density_fluid()); } + number Mass(const int levIndex, const int prtIndex, const number volume) + { return m_spParticleHandlerGlobal->Mass(levIndex, prtIndex, volume, m_spInterfaceHandlerLocal->get_density_fluid()); } + number MomOfInertia(const int levIndex, const int prtIndex) + { return m_spParticleHandlerGlobal->MomOfInertia(levIndex, prtIndex, m_spInterfaceHandlerLocal->get_density_fluid()); } + number MomOfInertia(const int levIndex, const int prtIndex, const number volume) + { return m_spParticleHandlerGlobal->MomOfInertia(levIndex, prtIndex, volume, m_spInterfaceHandlerLocal->get_density_fluid()); } + + number compute_volume(int levIndex, size_t prtIndex); + + void set_forceLog(bool val) { + m_bForceLog = val; + } + + private: + // member from base class + SmartPtr > m_spInterfaceHandlerLocal; + // new member + SmartPtr > m_spParticleHandlerGlobal; + + + // gravityConst for call during 'set_gravitational_rhs()' + number m_gravityConst; + + // boolian to add gravity force to global defect during 'add_local_vec_to_global_interface()' + bool m_bGravity; // default = false; + + // boolian to add repulsive force in 'add_rhs()' + bool m_bRepulsiveForce; + bool m_bGlowRepulsiveForce; + bool m_bMinimumCorrectionForce; + number m_rho; + number m_epsilon; + number m_repulsiveForce; + number m_repulsiveDistance; + + // used within 'set_gravitational_rhs()' for computation of rhs + number m_dt; // default = 0.0; + bool m_bTimeDep; + + // used within 'add_repulsive_force' for computation of rhs + double m_meanDiameter; + + + /// handles the call of'set_gravity()' exactly ONCE during 'modify_LocalData()' + std::vector m_bFlagGravity; // default = false + + /// handles the call of'set_gravity()' exactly ONCE during 'modify_LocalData()' + std::vector m_bFlagInertial; // default = false + + number m_volume; + bool m_bVolumeCompExact; + bool m_bUsualAss; // default = false; + + bool m_bForceLog; + +}; + + +} // end namespace NavierStokes +} // end namespace ug + + +#include "loc_to_glob_mapper_particle_impl.h" +#include "loc_to_glob_mapper_particle_tools.h" + + + +#endif /* PARTICLE_MAPPER_H_ */ diff --git a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h new file mode 100644 index 0000000..463b590 --- /dev/null +++ b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h @@ -0,0 +1,2775 @@ +/* + * moving_particle_impl.h + * + * Created on: 20.01.2015 + * Author: suze + */ + +#ifndef PARTICLE_MAPPER_IMPL_H_ +#define PARTICLE_MAPPER_IMPL_H_ + +namespace ug { +namespace NavierStokes { + +/////////////////////////////////////////////////////////// +// Implementation of the methods class +// 'ParticleHandlerGlobal' +/////////////////////////////////////////////////////////// + +// see particle_handler_global_impl.h/_tools.h + + +/////////////////////////////////////////////////////////// +// Implementation of the methods class +// 'ParticleMapper' +/////////////////////////////////////////////////////////// + + +template +number ParticleMapper:: +compute_volume(int levIndex, size_t prtIndex) +{ + bool output = false; + + if (dim == 2 && m_spInterfaceHandlerLocal->m_vBF.size() != 2 + && m_spInterfaceHandlerLocal->m_vBF.size() != 0) { + UG_LOG( + "m_spInterfaceHandlerLocal->m_vBF.size() = " << m_spInterfaceHandlerLocal->m_vBF.size() << "\n"); + UG_THROW("oha, this->m_vBF.size() != 2 && != 0:\n"); + } + + const bool useResized = true; + number dist = 0.0; + number baseArea = 0.0; + number height = 0.0; + number volume = 0.0; + MathVector midPoint(0.0); + std::vector > vCorners; + + const MathVector center = m_spParticleHandlerGlobal->get_center( + prtIndex); + std::vector < interfaceBF > &vBF = + m_spInterfaceHandlerLocal->get_boundary_faces(); + +// loop bf + for (size_t i = 0; i < vBF.size(); ++i) { + interfaceBF bf = vBF[i]; + + size_t nodeID = bf.node_id(); + if (!useResized) + nodeID = m_spInterfaceHandlerLocal->corner_orig(nodeID); + + vCorners.push_back(m_spInterfaceHandlerLocal->corner(nodeID)); + midPoint += m_spInterfaceHandlerLocal->corner(nodeID); + + baseArea += VecLength(bf.normal()); + + if (output) { + UG_LOG("i = " << i << "\n"); + UG_LOG("nodeID = " << nodeID << "\n"); + UG_LOG( + "this->corner(" << nodeID << ") = " << m_spInterfaceHandlerLocal->corner(nodeID) << "\n"); + UG_LOG("vCorners[" << i << "] = " << vCorners[i] << "\n"); + UG_LOG("midPoint = " << midPoint << "\n"); + UG_LOG( + "VecLength(bf.normal()) = " << VecLength(bf.normal()) << "\n"); + UG_LOG("baseArea = " << baseArea << "\n"); + } + } + + if (dim == 2 && vCorners.size() != 2 && vCorners.size() != 0) + UG_THROW("vCorners.size() != 2:" << vCorners.size() << "\n"); + + midPoint *= 0.5; + height = VecDistance(midPoint, center); + dist = VecDistance(vCorners[0], vCorners[1]); + + if (fabs(baseArea - dist) > 1e-9) + UG_THROW( + "baseArea != dist(corners): " << baseArea << " != " << dist << "\n"); + + volume = 0.5 * baseArea * height; + + if (output) { + UG_LOG("midPoint = " << midPoint << "\n"); + UG_LOG("height = " << height << "\n"); + UG_LOG("dist = " << dist << "\n"); + UG_LOG("return: volume = " << volume << "\n"); + } + +// update volume: + m_volume += volume; + + if (output) { + UG_LOG( + "nachher (levIndex = " << levIndex << "): m_volume = " << m_volume << "\n"); + UG_LOG("ref Volume = " << Volume(levIndex,prtIndex) << "\n"); + } + return volume; + +} + +template +int ParticleMapper:: +getMappingModus(size_t fct1, size_t dof1, size_t fct2, size_t dof2) { + + bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(dof1); + bool isPrtConn = m_spInterfaceHandlerLocal->remapped_fromInterface(dof2); + +// fluid->fluid: + if (!isPrtNode && !isPrtConn) + return 0; +// fluid->particle: + if (!isPrtNode && isPrtConn) { + if (fct2 == dim) + return 0; // = connection to pressure on interface! + else + return 1; + } +// particle->fluid: + if (isPrtNode && !isPrtConn) { + if (fct1 == dim) + return 0; // = ContEq on interface! + else + return 2; + } +// particle->particle: + if (isPrtNode && isPrtConn) { + if (fct1 == dim && fct2 == dim) + return 0; + else if (fct1 == dim) + return 1; // prt-vel in ContEq => fluid->particle + else if (fct2 == dim) { + if (m_spInterfaceHandlerLocal->elementModus() != OUTSIDE_DOM) + return 2; // pressure in prt-ImpEq => particle->fluid + else + return 4; + } else + return 3; // trans-rot/rot-trans + } + + return -1; + +} + +template +int ParticleMapper::getMappingModus_for2(size_t fct1, + size_t dof1, size_t fct2, size_t dof2) { + +// fluid->... + if (fct1 == _P_ || dof1 == 4) { + // fluid->fluid: + if (fct2 == _P_ || dof2 == 4) + return 0; + // fluid->particle: + else + return 1; + } +// particle->... + else { + // particle->fluid: + if (fct2 == _P_ || dof2 == 4) + return 2; + // particle->particle: + else + return 3; + } + + return -1; + +} + +template +void ParticleMapper::set_extraSol(vector_type& vec, + std::vector transInd, std::vector rotInd, + const int timeIndex, const int prtIndex) { + for (int d = 0; d < dim; ++d) { + // A. if the linear velocity is given by the user, is needs NOT to be set + if (!m_spParticleHandlerGlobal->get_DoF_modus_linear(prtIndex)) + m_spParticleHandlerGlobal->set_extraSolTrans( + DoFRef(vec, transInd[d]), prtIndex, timeIndex, d); + // B. if the angular velocity is given by the user, is needs NOT to be set + if (!m_spParticleHandlerGlobal->get_DoF_modus_anguar(prtIndex)) + m_spParticleHandlerGlobal->set_extraSolRot(DoFRef(vec, rotInd[d]), + prtIndex, timeIndex, d); + } +} + +template +void ParticleMapper::modify_GlobalSol( + SmartPtr > vSolMod, + ConstSmartPtr > vSol, + ConstSmartPtr dd) { + UG_LOG("begin modify_Glob\n"); + +// some checks + if (vSol->size() != 2) + UG_THROW( + "ParticleMapper::modify_GlobalSol: method needs exactly two time points."); + if (!is_time_dependent()) + set_time_dependent(true); + + const int levIndex = get_Index(dd->grid_level(), dd); + + for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + m_bFlagInertial[p] = true; + + if (gravitation_force()) { + UG_LOG("modify_GlobalSol: set m_bFlagGravity from 'false' to 'true'\n"); + m_bFlagGravity[p] = true; + } + + // linear AND angular velocity are given by the user: + if (m_spParticleHandlerGlobal->get_DoF_modus_linear(p) + && m_spParticleHandlerGlobal->get_DoF_modus_angular(p)) + continue; + + std::vector ElemList = + m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + +#ifdef UG_PARALLEL + UG_LOG( + "1 NavierStokes::modify_GlobalSol: ElemList.size(): " << ElemList.size() << "\n"); + if (ElemList.size() == 0) { + UG_LOG( + "2 NavierStokes::modify_GlobalSol: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + continue; + } +#endif + + // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) + std::vector < DoFIndex > transInd = + m_spParticleHandlerGlobal->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd( + levIndex, p); +#ifdef UG_DEBUG + UG_LOG("in modify_GlobalSol: transInd: " << transInd[0] << "\n"); + UG_LOG("in modify_GlobalSol: rotInd: " << rotInd[0] << "\n"); + + UG_LOG( + "VORHER: modify_GlobalSol transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); + UG_LOG( + "VORHER: modify_GlobalSol transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); + UG_LOG( + "VORHER: modify_GlobalSol rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); + UG_LOG( + "VORHER: modify_GlobalSol rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); +#endif + // loop all time points and assemble them + for (int i = vSol->size() - 1; i >= 0; --i) { + number solution; + +#ifdef UG_DEBUG + UG_LOG("in modify_GlobalSol: transInd: " << transInd[0] << "\n"); + + + //set_extraSol(*vSol->solution(i), transInd, rotInd, i, p); + + /* MathVector solution = m_spParticleHandlerGlobal->get_transSol(p,i); + m_spParticleHandlerGlobal->set_extraSolTrans(solution, p, i); + UG_LOG("solution(" << i << ") = " << solution << "\n"); + + solution = m_spParticleHandlerGlobal->get_transSol(p,i); + m_spParticleHandlerGlobal->set_extraSolRot(solution, p, i); + + UG_LOG("solution(" << i << ") = " << solution << "\n"); + */ + for (int d = 0; d < dim; ++d) { + UG_LOG("d = " << d << "\n"); + + // A. if the linear velocity is given by the user, it needs NOT to be set + if (!m_spParticleHandlerGlobal->get_DoF_modus_linear(p)) { + UG_LOG("1: solution = " << solution << "\n"); + UG_LOG( + "in modify_GlobalSol: transInd[d]: " << transInd[d] << "\n"); + + solution = DoFRef(*vSol->solution(i), transInd[d]); + UG_LOG("2: solution = " << solution << "\n"); + + m_spParticleHandlerGlobal->set_extraSolTrans(solution, p, i, + d); + UG_LOG("transSol(" << i << " = " << solution << "\n"); + } + + // B. if the angular velocity is given by the user, it needs NOT to be set + if (!m_spParticleHandlerGlobal->get_DoF_modus_angular(p)) { + UG_LOG("3: solution = " << solution << "\n"); + + solution = DoFRef(*vSol->solution(i), rotInd[d]); + UG_LOG("4: solution = " << solution << "\n"); + + m_spParticleHandlerGlobal->set_extraSolRot(solution, p, i, + d); + UG_LOG("rotSol(" << i << " = " << solution << "\n"); + } + + } +#else + for (int d = 0; d < dim; ++d) { + if (!m_spParticleHandlerGlobal->get_DoF_modus_linear(p)) { + solution = DoFRef(*vSol->solution(i), transInd[d]); + m_spParticleHandlerGlobal->set_extraSolTrans(solution, p, i, d); + } + + // B. if the angular velocity is given by the user, is needs NOT to be set + if (!m_spParticleHandlerGlobal->get_DoF_modus_angular(p)) { + solution = DoFRef(*vSol->solution(i), rotInd[d]); + m_spParticleHandlerGlobal->set_extraSolRot(solution, p, i, d); + } + } +#endif + } // end time series loop +#ifdef UG_DEBUG + UG_LOG( + "NACHHER: modify_GlobalSol transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); + UG_LOG( + "NACHHER: modify_GlobalSol transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); + UG_LOG( + "NACHHER: modify_GlobalSol rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); + UG_LOG( + "NACHHER: modify_GlobalSol rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); +#endif + } // end particle loop + + UG_LOG("end modify_Glob\n"); + +} + +template +void ParticleMapper::modify_GlobalSol(vector_type& uMod, + const vector_type& u, ConstSmartPtr dd) { + if (is_time_dependent()) + set_time_dependent(false); + + const int levIndex = get_Index(dd->grid_level(), dd); + + for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + if (gravitation_force()) { + UG_LOG( + "modify_GlobalSol: set m_bFlagGravity from 'false' to 'true'\n"); + m_bFlagGravity[p] = true; + } + + // linear AND angular velocity are given by the user: + if (m_spParticleHandlerGlobal->get_DoF_modus_linear(p) + && m_spParticleHandlerGlobal->get_DoF_modus_angular(p)) { +#ifdef UG_DEBUG + UG_LOG( + "continue... in modify_GlobalSol for transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); + UG_LOG( + "continue... in modify_GlobalSol for transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); + UG_LOG( + "continue... in modify_GlobalSol for rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); + UG_LOG( + "continue... in modify_GlobalSol for rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); +#endif + continue; + } + + std::vector ElemList = + m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + +#ifdef UG_PARALLEL + UG_LOG( + "1 NavierStokes::modify_GlobalSol: ElemList.size(): " << ElemList.size() << "\n"); + if (ElemList.size() == 0) { + UG_LOG( + "2 NavierStokes::modify_GlobalSol: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + continue; + } +#endif + + // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) + std::vector < DoFIndex > transInd = + m_spParticleHandlerGlobal->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd( + levIndex, p); +#ifdef UG_DEBUG + UG_LOG( + "VORHER: modify_GlobalSol transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); + UG_LOG( + "VORHER: modify_GlobalSol transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); + UG_LOG( + "VORHER: modify_GlobalSol rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); + UG_LOG( + "VORHER: modify_GlobalSol rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); +#endif + // set_extraSol(u, transInd, rotInd, 0, p); + number solution; + for (int d = 0; d < dim; ++d) { +#ifdef UG_DEBUG + UG_LOG("transInd[" << d << "] = " << transInd[d] << "\n"); + UG_LOG("rotInd[" << d << "] = " << rotInd[d] << "\n"); +#endif + // A. if the linear velocity is given by the user, is needs NOT to be set + if (!m_spParticleHandlerGlobal->get_DoF_modus_linear(p)) { + solution = DoFRef(u, transInd[d]); + m_spParticleHandlerGlobal->set_extraSolTrans(solution, p, 0, d); + UG_LOG("transSol = " << solution << "\n"); + } + + // B. if the angular velocity is given by the user, is needs NOT to be set + if (!m_spParticleHandlerGlobal->get_DoF_modus_angular(p)) { + solution = DoFRef(u, rotInd[d]); + m_spParticleHandlerGlobal->set_extraSolRot(solution, p, 0, d); + UG_LOG("rotSol = " << solution << "\n"); + } + + } +#ifdef UG_DEBUG + UG_LOG( + "NACHHER: modify_GlobalSol transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); + UG_LOG( + "NACHHER: modify_GlobalSol transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); + UG_LOG( + "NACHHER: modify_GlobalSol rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); + UG_LOG( + "NACHHER: modify_GlobalSol rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); +#endif + } // end particle loop + +} + +template +void ParticleMapper::map_local_data(LocalVector& d) { + LocalIndices ind = d.get_indices(); + +// initialize tmp data + LocalVector tmpLocD; + tmpLocD.resize(d.get_indices()); + +// operator= exists only for single value! => set to zero and add + tmpLocD = 0.0; + tmpLocD += d; + +// copy old local vector to new local algebra + for (size_t fct = 0; fct < ind.num_fct(); ++fct) + for (size_t dof = 0; dof < ind.num_dof(fct); ++dof) { + size_t _dof = m_spInterfaceHandlerLocal->corner_orig(dof); + d(fct, dof) = tmpLocD(fct, _dof); + } + +} + +template +void ParticleMapper:: +modify_LocalData(LocalMatrix& locJ, LocalVector& locU, ConstSmartPtr dd) +{ +// A. INSIDE_DOM: do nothing + if (m_spInterfaceHandlerLocal->elementModus() == INSIDE_DOM) + return; + +// B. resize local indices: + if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE + && m_spInterfaceHandlerLocal->interface_id_all().size() == 2) + { + if (!m_spInterfaceHandlerLocal->StdFV_assembling()) + resize_local_indices(locU, 5); + else + resize_local_indices(locU); + } + else + resize_local_indices(locU); + +// C. resize local data: + const LocalIndices& ind = m_spInterfaceHandlerLocal->get_local_indices(); + locU.resize(ind); + locJ.resize(ind); + + return; +} + +template +void ParticleMapper::modify_LocalData( + LocalVectorTimeSeries& uT, LocalMatrix& locJ, LocalVector& locU, + ConstSmartPtr dd) { + // A. INSIDE_DOM: do nothing + if (m_spInterfaceHandlerLocal->elementModus() == INSIDE_DOM) + return; + + for (int i = uT.size() - 1; i >= 0; --i) { + // resize local indices: + if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE + && m_spInterfaceHandlerLocal->interface_id_all().size() == 2) { + if (!m_spInterfaceHandlerLocal->StdFV_assembling()) + resize_local_indices(locU, 5); + else + resize_local_indices(locU); + } else + resize_local_indices(locU); + + // resize local data: + const LocalIndices& ind = + m_spInterfaceHandlerLocal->get_local_indices(); + locU.resize(ind); + locJ.resize(ind); + uT.solution(i).resize(ind); + + } + + return; +} + +template +void ParticleMapper::set_QuadriSol(LocalVector& locU, + LocalVector& locD) { + + if (locU.num_all_dof(0) != 5) + UG_THROW( + "ParticleMapper:set_QuadriSol(): number of DoFs should be 5, but is " << locU.num_all_dof(0) << "\n"); + +// 3. get velocities of the 2 particles: + MathVector transSol1 = m_spParticleHandlerGlobal->get_transSol(0, 0); + MathVector rotSol1 = m_spParticleHandlerGlobal->get_rotSol(0, 0); + MathVector transSol2 = m_spParticleHandlerGlobal->get_transSol(1, 0); + MathVector rotSol2 = m_spParticleHandlerGlobal->get_rotSol(1, 0); + +// resize local data as done during 'modify_LocalData' +// --> but there with num_co = 3 for the Triangle with inside node! + for (size_t fct = 0; fct < locU.num_fct() - 1; ++fct) + for (size_t dof = 0; dof < locU.num_all_dof(fct); ++dof) { + MathMatrix rotationMatCo = + m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_co(dof)); + + UG_LOG( + "radial(" << dof << ": " << m_spInterfaceHandlerLocal->radial_at_co(dof) << "\n"); + + // write solution of particle with prtIndex = 0: + if (dof < 2) { + locU(fct, dof) = transSol1[fct]; + for (int d = 0; d < dim; ++d) + locU(fct, dof) += rotationMatCo[fct][d] * rotSol1[d]; + } + // write solution of particle with prtIndex = 1: + else { + locU(fct, dof) = transSol2[fct]; + for (int d = 0; d < dim; ++d) + locU(fct, dof) += rotationMatCo[fct][d] * rotSol2[d]; + } + } + + m_spInterfaceHandlerLocal->set_QuadriSol(locD, locU); + + UG_LOG("after set_QuadriSol: locU = \n" << locU << "\n"); + UG_LOG("after set_QuadriSol: locD = \n" << locD << "\n"); + + UG_LOG( + "after set_QuadriSol: m_quadriLocU = \n" << m_spInterfaceHandlerLocal->m_quadriLocU << "\n"); + UG_LOG( + "after set_QuadriSol: m_quadriLocD = \n" << m_spInterfaceHandlerLocal->m_quadriLocD << "\n"); + +} + +template +void ParticleMapper::modify_LocalData(LocalVector& locD, + LocalVector& tmpLocD, LocalVector& locU, + ConstSmartPtr dd) { + // A. INSIDE_DOM: do nothing + if (m_spInterfaceHandlerLocal->elementModus() == INSIDE_DOM) + return; + + // resize local indices: + if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE + && m_spInterfaceHandlerLocal->interface_id_all().size() == 2) { + if (!m_spInterfaceHandlerLocal->StdFV_assembling()) + resize_local_indices(locU, 5); + else + resize_local_indices(locU); + } else + resize_local_indices(locU); + +// resize local data: + const LocalIndices& ind = m_spInterfaceHandlerLocal->get_local_indices(); + locU.resize(ind); + locD.resize(ind); + tmpLocD.resize(ind); +// UG_LOG("---> locD = \n" << locD << "\n"); +// UG_LOG("---> locU = \n" << locU << "\n"); + + // ToDo: domainDisc::adjust_solution() globally via domainDisc or Constraint! + int prtIndex = get_prtIndex(); + + const MathVector center = m_spParticleHandlerGlobal->get_center( + prtIndex); + + MathVector transSol = m_spParticleHandlerGlobal->get_transSol(prtIndex, + 0); + MathVector rotSol = m_spParticleHandlerGlobal->get_rotSol(prtIndex, 0); + +// B. OUTSIDE_DOM: write solution for ALL corners + if (m_spInterfaceHandlerLocal->elementModus() == OUTSIDE_DOM) { + for (size_t fct = 0; fct < locU.num_fct() - 1; ++fct) + for (size_t dof = 0; dof < locU.num_all_dof(fct); ++dof) { + //MathMatrix rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->corner(dof)); + + MathVector radialCo; + VecSubtract(radialCo, m_spInterfaceHandlerLocal->corner(dof), + center); + MathMatrix rotationMatCo = + m_spParticleHandlerGlobal->get_rotationMat(radialCo); + + // set solution + locU(fct, dof) = transSol[fct]; + for (int d = 0; d < dim; ++d) + locU(fct, dof) += rotationMatCo[fct][d] * rotSol[d]; + + } + } + +// C. CUT_BY_INTERFACE: write solution for interface corners + if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_INTERFACE + || (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE + && m_spInterfaceHandlerLocal->StdFV_assembling())) { + map_local_data(locU); + + //for(size_t fct=0; fct < locU.num_fct()-1; ++fct) // VORSICHT: locU.num_fct() = 1 fuer shear_interface...warum auch immer... + for (size_t fct = 0; fct < locU.num_fct() - 1; ++fct) { + for (size_t i = 0; + i < m_spInterfaceHandlerLocal->interface_id_all().size(); + ++i) { + size_t interfaceID = m_spInterfaceHandlerLocal->interface_id(i); + + MathMatrix rotationMatCo = + m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_co( + interfaceID)); + + // set solution + locU(fct, interfaceID) = transSol[fct]; + + for (int d = 0; d < dim; ++d) + locU(fct, interfaceID) += rotationMatCo[fct][d] * rotSol[d]; + + } + } + } + +// D. CUT_BY_2_INTERFACE: + if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE) { + if (!m_spInterfaceHandlerLocal->StdFV_assembling()) + set_QuadriSol(locU, locD); + } + +} + +template +void ParticleMapper::modify_LocalData( + LocalVectorTimeSeries& uT, LocalVector& locD, LocalVector& tmpLocD, + LocalVector& locU, ConstSmartPtr dd, size_t t) { + +// 'modify_LocalData()' is called twice (for t=0, t=1) in elem_disc_assemble_util; +// BUT: 'map_local_data()' may be called only once! + if (t == 1) + return; + + // A. INSIDE_DOM: do nothing + if (m_spInterfaceHandlerLocal->elementModus() == INSIDE_DOM) + return; + + // ToDo: domainDisc::adjust_solution() globally via domainDisc or Constraint! + int prtIndex = get_prtIndex(); + const MathVector center = m_spParticleHandlerGlobal->get_center( + prtIndex); + +// resize local indices: + if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE + && m_spInterfaceHandlerLocal->interface_id_all().size() == 2) { + if (!m_spInterfaceHandlerLocal->StdFV_assembling()) + resize_local_indices(locU, 5); + else + resize_local_indices(locU); + } else + resize_local_indices(locU); + +// resize local data: + const LocalIndices& ind = m_spInterfaceHandlerLocal->get_local_indices(); + locU.resize(ind); + locD.resize(ind); + tmpLocD.resize(ind); + + // loop all time points and assemble them + for (int i = uT.size() - 1; i >= 0; --i) { + + uT.solution(i).resize(ind); + + LocalVector* vecMod = &uT.solution(i); + + MathVector transSol = m_spParticleHandlerGlobal->get_transSol( + prtIndex, i); + MathVector rotSol = m_spParticleHandlerGlobal->get_rotSol(prtIndex, + i); + + // B. OUTSIDE_DOM: write solution for ALL corners + if (m_spInterfaceHandlerLocal->elementModus() == OUTSIDE_DOM) { + for (size_t fct = 0; fct < locU.num_fct() - 1; ++fct) + for (size_t dof = 0; dof < locU.num_all_dof(fct); ++dof) { + MathVector radialCo; + VecSubtract(radialCo, + m_spInterfaceHandlerLocal->corner(dof), center); + MathMatrix rotationMatCo = + m_spParticleHandlerGlobal->get_rotationMat( + radialCo); + + // set solution + (*vecMod)(fct, dof) = transSol[fct]; + for (int d = 0; d < dim; ++d) + (*vecMod)(fct, dof) += rotationMatCo[fct][d] + * rotSol[d]; + + } + } + + // C. CUT_BY_INTERFACE: write solution for interface corners + if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_INTERFACE + || (m_spInterfaceHandlerLocal->elementModus() + == CUT_BY_2_INTERFACE + && m_spInterfaceHandlerLocal->StdFV_assembling())) { + map_local_data(*vecMod); + + for (size_t fct = 0; fct < locU.num_fct() - 1; ++fct) { + for (size_t i = 0; + i < m_spInterfaceHandlerLocal->interface_id_all().size(); + ++i) { + size_t interfaceID = + m_spInterfaceHandlerLocal->interface_id(i); + MathMatrix rotationMatCo = + m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_co( + interfaceID)); + + // set solution + (*vecMod)(fct, interfaceID) = transSol[fct]; + for (int d = 0; d < dim; ++d) + (*vecMod)(fct, interfaceID) += rotationMatCo[fct][d] + * rotSol[d]; + } + } + + } + + // D. CUT_BY_2_INTERFACE: + if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE) { + if (!m_spInterfaceHandlerLocal->StdFV_assembling()) + UG_THROW("modify_LocalData(): CUT_BY_2_INTERFACE\n"); //set_QuadriSol(locU, locD); + } + + } // end time loop + +} + +/* + template < typename TDomain, typename TAlgebra> + void ParticleMapper:: + modify_LocalSol(SmartPtr vSolMod, + ConstSmartPtr vSol, ConstSmartPtr dd) + { + // check current and old solution + if(vSol->size() != 2) + UG_THROW("ParParticleMapperticle::modify_LocalSol: " + " Stabilization needs exactly two time points."); + + // A. INSIDE_DOM: do nothing + if(m_spInterfaceHandlerLocal->elementModus() == INSIDE_DOM) + return; + + // ToDo: domainDisc::adjust_solution() globally via domainDisc or Constraint! + int prtIndex = get_prtIndex(); + + // loop all time points and assemble them + for(int i = vSol->size()-1; i >= 0 ; --i) + { + MathVector transSol = m_spParticleHandlerGlobal->get_transSol(prtIndex, i); + MathVector rotSol = m_spParticleHandlerGlobal->get_rotSol(prtIndex, i); + + LocalVector* vecMod = &vSolMod->solution(i); + + // B. OUTSIDE_DOM: write solution for ALL corners + if(m_spInterfaceHandlerLocal->elementModus() == OUTSIDE_DOM) + { + for(size_t fct = 0; fct < dim; ++fct) + for(size_t dof=0; dof < vecMod->num_all_dof(fct); ++dof) + { + MathMatrix rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->corner(dof)); + + // set solution + (*vecMod)(fct,dof) = transSol[fct]; + for ( int d = 0; d < dim; ++d ) + (*vecMod)(fct,dof) += rotationMatCo[fct][d]*rotSol[d]; + + } + } + + // C. CUT_BY_INTERFACE: write solution for interface corners + if(m_spInterfaceHandlerLocal->elementModus() == CUT_BY_INTERFACE) + { + for(size_t fct = 0; fct < dim; ++fct) + for(size_t i = 0; i < m_spInterfaceHandlerLocal->interface_id_all().size(); ++i) + //for(size_t dof=0; dof < lvec.num_all_dof(fct); ++dof) + { + size_t interfaceID = m_spInterfaceHandlerLocal->interface_id(i); + size_t dof = m_spInterfaceHandlerLocal->corner_orig(interfaceID); + + MathMatrix rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(dof)); + + // set solution + (*vecMod)(fct,dof) = transSol[fct]; + for ( int d = 0; d < dim; ++d ) + (*vecMod)(fct,dof) += rotationMatCo[fct][d]*rotSol[d]; + + } + } + + } // end time loop + + } + + */ + +template +void ParticleMapper:: +set_identity_mat_constraint(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd) +{ +// get levIndex + const int levIndex = get_Index(dd->grid_level(), dd); + +// get local indices + const LocalIndices& rowInd = lmat.get_row_indices(); + + for (size_t fct1 = 0; fct1 < lmat.num_all_row_fct(); ++fct1) + for (size_t dof1 = 0; dof1 < lmat.num_all_row_dof(fct1); ++dof1) { + const size_t _dof1 = m_spInterfaceHandlerLocal->corner_orig(dof1); + const size_t rowIndex = rowInd.index(fct1, _dof1); + const size_t rowComp = rowInd.comp(fct1, _dof1); + + // m_spParticleHandlerGlobal->is_extraDoF returns false, if particle velocity is given by the model + bool is_extraDoF = m_spParticleHandlerGlobal->is_extraDoF( + DoFIndex(rowIndex, rowComp), levIndex); + + // IFF node is no transInd/rotInd-node and no interface node! + bool is_interfaceDoF = true; + // on interface, only pressure is real DoF: + if (fct1 != dim) + is_interfaceDoF = false; + else if (m_spInterfaceHandlerLocal->StdFV_assembling()) { + + is_interfaceDoF = + m_spInterfaceHandlerLocal->remapped_fromInterface( + _dof1); + //is_interfaceDoF = true; //m_spInterfaceHandlerLocal->lies_onInterface(_dof1); + + } else + is_interfaceDoF = + m_spInterfaceHandlerLocal->remapped_fromInterface( + _dof1); + + // DoFs on interface OR for translational/angular velocity need to remain free + if (is_interfaceDoF || is_extraDoF) + continue; + else + BlockRef(mat(rowIndex, rowIndex), rowComp, rowComp) = 1.0; + } + +} + +template +void ParticleMapper::add_local_mat_to_global( + matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd) { + /* ATTENTION: + * 'mat' contains entries for ALL ElemDiscs! + * But: apply add_local_mat_to_global_interface() only for + * (some) specified ElemDiscs! + * + * solution A: 1. map via 'acess_by_map(m_pElemDisc->map())' + * 2. set mat(access_by_map()-indices) to zero + * 3. apply usual AddLocalMatrixToGlobal() + * + * solution B: vElemDisc-loop as in DataEvaluator: + * // compute elem-owned mapping + try{ + for(size_t i = 0; i < m_vElemDisc[type].size(); ++i) + m_vElemDisc[type][i]->do_add_jac_A_elem(J, u, elem, vCornerCoords); + } + + solution C: AssemblingTuner becomes also member of IElemDisc, + NOT DomainDisc + */ + + ElementModus modus = m_spInterfaceHandlerLocal->elementModus(); + LocalMatrix locJ = lmat; + + switch (modus) { + case OUTSIDE_DOM: + map_all_local_mat_to_transDoF(mat, lmat, dd); // hier steht mass term aus 'add_jac_M_elem()' + if (0) //m_spInterfaceHandlerLocal->StdFV_assembling() ) + add_local_mat_to_global_interface(mat, lmat, dd); + set_identity_mat_constraint(mat, lmat, dd); //IFF element does NOT include transInd/rotInd-node! + break; + case INSIDE_DOM: + AddLocalMatrixToGlobal(mat, lmat); + break; + case CUT_BY_INTERFACE: + add_local_mat_to_global_interface(mat, lmat, dd); + break; + case CUT_BY_2_INTERFACE: + add_local_mat_to_global_interface_for2(mat, lmat, dd); + break; + default: + throw(UGError("Error in IInterfaceMapper::add_local_mat_to_global()!")); + + } + +} + +template +void ParticleMapper::add_local_vec_to_global( + vector_type& vec, const LocalVector& lvec, + ConstSmartPtr dd) +{ + + ElementModus modus = m_spInterfaceHandlerLocal->elementModus(); + + switch (modus) { + case OUTSIDE_DOM: + if (0) //m_spInterfaceHandlerLocal->StdFV_assembling() ) + add_local_vec_to_global_interface(vec, lvec, dd); + // add nothing; ?? + // ToDo map_all_local_vec_to_transDoF(vec, lvec, dd); // hier steht jetzt timedep. gravity force aus 'add_def_A_elem()' + // _A_ und NICHT _M_, da zeit faktor notwendig! + // set_zero_defect(); --> NOT necessary, since NO adding => 0.0 + break; + case INSIDE_DOM: + AddLocalVector(vec, lvec); + break; + case CUT_BY_INTERFACE: + add_local_vec_to_global_interface(vec, lvec, dd); + break; + case CUT_BY_2_INTERFACE: + add_local_vec_to_global_interface_for2(vec, lvec, dd); + break; + default: + throw(UGError("Error in IInterfaceMapper::add_local_vec_to_global()!")); + + } + +} + + +template +void ParticleMapper:: +add_mass_part_jac(matrix_type& mat, std::vector transInd, std::vector rotInd, + const int levIndex, const int prtIndex) { + number volume; + + if (m_bVolumeCompExact) + volume = Volume(levIndex, prtIndex); + else + volume = compute_volume(levIndex, prtIndex); + + // add mass term to global matrix (instead of using IConstraint::adjust_jacobian() ) + for (int d = 0; d < dim; ++d) { + DoFRef(mat, transInd[d], transInd[d]) += Mass(levIndex, prtIndex, + volume); + // for dim = 2: the second DoF of rotInd is unused! + if (dim == 3 || d == 0) + DoFRef(mat, rotInd[d], rotInd[d]) += MomOfInertia(levIndex, + prtIndex, volume); + } + + if (m_bVolumeCompExact) + m_bFlagInertial[prtIndex] = false; // adding mass/inertia terms only ONCE!! +} + +// call for 'OUTSIDE_DOM' +template +void ParticleMapper::map_all_local_mat_to_transDoF( + matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd) { + +} + +/* + template + void ParticleMapper:: + add_local_mat_to_global_FT_for2(matrix_type& mat, const LocalMatrix& lmat, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2) + { + UG_LOG("start add_local_mat_to_global_FT_for2()\n"); + + UG_LOG("transInd1: " << transInd1[0] << "\n"); + UG_LOG("transInd2: " << transInd2[0] << "\n"); + UG_LOG("rotInd1: " << rotInd1[0] << "\n"); + UG_LOG("rotInd2: " << rotInd2[0] << "\n"); + + MathMatrix rotationMatCo, rotationMatIP, rotationMatIP_transposed; + std::vector transInd_from, rotInd_from; + std::vector transInd_to, rotInd_to; + + UG_LOG("lmat.num_all_row_dof(0) = \n" << lmat.num_all_row_dof(0) << "\n"); + UG_LOG("lmat.num_all_row_dof(1) = \n" << lmat.num_all_row_dof(1) << "\n"); + if ( lmat.num_all_row_dof(0) != 4 ) + UG_THROW("lmat.num_all_row_dof(2) = \n" << lmat.num_all_row_dof(2) << "\n"); + + for(size_t fct1=0; fct1 < 2; ++fct1) + for(size_t fct2=0; fct2 < 2; ++fct2) + for(size_t dof1=0; dof1 < 4; ++dof1) + for(size_t dof2=0; dof2 < 4; ++dof2) + { + rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(dof2)); + rotationMatIP = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_ip(dof1)); + + UG_LOG("dof1: " << dof1 << ", m_spInterfaceHandlerLocal->radial_at_ip(dof1): " << m_spInterfaceHandlerLocal->radial_at_ip(dof1) << "\n"); + UG_LOG("dof2: " << dof2 << ", m_spInterfaceHandlerLocal->radial_at_co(dof2): " << m_spInterfaceHandlerLocal->radial_at_co(dof2) << "\n"); + + + // coupling FROM particle1 + if ( dof1 < 2 ) { transInd_from = transInd1; rotInd_from = rotInd1; } + // coupling FROM particle2 + else { transInd_from = transInd2; rotInd_from = rotInd2; } + // coupling TO particle1 + if ( dof2 < 2 ) { transInd_to = transInd1; rotInd_to = rotInd1; } + // coupling TO particle2 + else { transInd_to = transInd2; rotInd_to = rotInd2; } + + UG_LOG("transInd_from: " << transInd_from[0] << "\n"); + UG_LOG("rotInd_from: " << rotInd_from[0] << "\n"); + UG_LOG("transInd_to: " << transInd_to[0] << "\n"); + UG_LOG("rotInd_to: " << rotInd_to[0] << "\n"); + + UG_THROW("check it out...\n"); + + // trans-trans + DoFRef(mat, transInd_from[fct1], transInd_to[fct2]) + += lmat.value(fct1,dof1,fct2,dof2); + + // trans-rot + for ( size_t cmp = 0; cmp < dim; ++cmp ) + DoFRef(mat, transInd_from[fct1], rotInd_to[cmp]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp]; + + // rot-trans + for ( size_t cmp = 0; cmp < dim; ++cmp ) + DoFRef(mat, rotInd_from[cmp], transInd_to[fct2]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatIP[fct1][cmp]; + + // rot-rot + for ( size_t cmp1 = 0; cmp1 < dim; ++cmp1 ) + for ( size_t cmp2 = 0; cmp2 < dim; ++cmp2 ) + DoFRef(mat, rotInd_from[cmp1], rotInd_to[cmp2]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp2]*rotationMatIP[fct1][cmp1]; + + } // end dof2-loop + + + + const LocalIndices& rowInd = lmat.get_row_indices(); + const LocalIndices& colInd = lmat.get_col_indices(); + + // FIRST: assemble connections between the 2 particles + for(size_t fct1=0; fct1 < lmat.num_all_row_fct(); ++fct1) + for(size_t dof1=0; dof1 < lmat.num_all_row_dof(fct1); ++dof1) + { + const DoFIndex indexRow = DoFIndex(rowInd.index(fct1,dof1), rowInd.comp(fct1,dof1)); + + for(size_t fct2=0; fct2 < lmat.num_all_col_fct(); ++fct2) + for(size_t dof2=0; dof2 < lmat.num_all_col_dof(fct2); ++dof2) + { + const DoFIndex indexCol = DoFIndex(colInd.index(fct2,dof2), colInd.comp(fct2,dof2)); + + rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(dof2)); + rotationMatIP = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_ip(dof1)); + + Transpose(rotationMatIP_transposed, rotationMatIP); + + size_t interfaceID; + + + size_t modus = getMappingModus(fct1, dof1, fct2, dof2); + switch(modus) + { + case 0: + { + DoFRef(mat, indexRow, indexCol) + += lmat.value(fct1,dof1,fct2,dof2); + } break; + case 1: + { + // A: get DoFIndex for connection to one of the 2 particles + bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(dof2, interfaceID); + if ( interfaceID < 2 ) + { transInd_to = transInd1; rotInd_to = rotInd1; } + else + { transInd_to = transInd2; rotInd_to = rotInd2; } + + // B: finally assemble connection: + DoFRef(mat, indexRow, transInd_to[fct2]) + += lmat.value(fct1,dof1,fct2,dof2); + + for ( size_t cmp = 0; cmp < dim; ++cmp ){ + DoFRef(mat, indexRow, rotInd_to[cmp]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp]; + } + + } break; + case 2: + { + // A: get DoFIndex for connection to one of the 2 particles + bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(dof1, interfaceID); + if ( interfaceID < 2 ) + { transInd_from = transInd1; rotInd_from = rotInd1; } + else + { transInd_from = transInd2; rotInd_from = rotInd2; } + + // B: finally assemble connection: + DoFRef(mat, transInd_from[fct1], indexCol) + += lmat.value(fct1,dof1,fct2,dof2); + + for ( size_t cmp = 0; cmp < dim; ++cmp ) + { + if ( 1) //fct2 != dim ) + { + DoFRef(mat, rotInd_from[cmp], indexCol) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatIP[fct1][cmp]; + } + } + + } break; + case 3: + { + // A: get DoFIndex for connection to one of the 2 particles + bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(dof1, interfaceID); + if ( interfaceID < 2 ) + { transInd_from = transInd1; rotInd_from = rotInd1; } + else + { transInd_from = transInd2; rotInd_from = rotInd2; } + + isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(dof2, interfaceID); + if ( interfaceID < 2 ) + { transInd_to = transInd1; rotInd_to = rotInd1; } + else + { transInd_to = transInd2; rotInd_to = rotInd2; } + + // B: finally assemble connection: + // trans-trans + DoFRef(mat, transInd_from[fct1], transInd_to[fct2]) + += lmat.value(fct1,dof1,fct2,dof2); + + // trans-rot ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) + for ( size_t cmp = 0; cmp < dim; ++cmp ) + DoFRef(mat, transInd_from[fct1], rotInd_to[cmp]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp]; + + + for ( size_t cmp = 0; cmp < dim; ++cmp ) + DoFRef(mat, rotInd_from[cmp], transInd_to[fct2]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatIP[fct1][cmp]; + + + for ( size_t cmp1 = 0; cmp1 < dim; ++cmp1 ) + for ( size_t cmp2 = 0; cmp2 < dim; ++cmp2 ) + DoFRef(mat, rotInd_from[cmp1], rotInd_to[cmp2]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp2]*rotationMatIP[fct1][cmp1]; + + } + break; + case 4:{// to pressure outside: sum = e-20 => skip! + } + break; + + default: + throw(UGError("Error in LocToGlob!")); + + } // end switch-cases + + } // end dof2-loop + + //////////////////////////////////////////////////////////////////////////////////////////////// + // finally set dirichlet row for velocity DoFs on interface: + // ---> also done during 'set_identity_mat_constraint()', BUT only for OUTSIDE_DOM-elements!! + //////////////////////////////////////////////////////////////////////////////////////////////// + + } // end dof1-loop + + + + if (0 ) // m_spInterfaceHandlerLocal->interface_id_all().size() == 4 ) + UG_THROW("end add_local_mat_to_gloabal_FT_for2()\n\n"); + + + } + */ + +// call for 'CUT_BY_2_INTERFACE' +template +void ParticleMapper::add_local_mat_to_global_interface_for2( + matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd) +{ +// get data + const int levIndex = get_Index(dd->grid_level(), dd); + std::vector < DoFIndex > transInd1, rotInd1, transInd2, rotInd2; + m_spParticleHandlerGlobal->get_global_indices(transInd1, rotInd1, levIndex, + 0); + m_spParticleHandlerGlobal->get_global_indices(transInd2, rotInd2, levIndex, + 1); + + UG_LOG( + "____________________________________________________________________\n"); + + for (size_t i = 0; i < m_spInterfaceHandlerLocal->m_vCornerCoords.size(); + ++i) + UG_LOG( + "m_vCornerCoords = " << m_spInterfaceHandlerLocal->m_vCornerCoords[i] << "\n"); + for (size_t i = 0; + i < m_spInterfaceHandlerLocal->m_vOriginalCornerID.size(); ++i) + UG_LOG( + "Original: id = " << m_spInterfaceHandlerLocal->m_vOriginalCornerID[i] << "\n"); + UG_LOG("\n"); + for (size_t i = 0; i < m_spInterfaceHandlerLocal->m_vInterfaceID.size(); + ++i) + UG_LOG( + "Interface: id = " << m_spInterfaceHandlerLocal->m_vInterfaceID[i] << "\n"); + UG_LOG("\n"); + + UG_LOG( + "____________________________________________________________________\n"); + + if (!UsualAss()) + if (m_spInterfaceHandlerLocal->StdFV_assembling()) + add_local_mat_to_global_FT_for2_StdFV(mat, lmat, transInd1, rotInd1, + transInd2, rotInd2); + else + add_local_mat_to_global_FT_for2(mat, lmat, transInd1, rotInd1, + transInd2, rotInd2); + else + UG_THROW( + "add_local_mat_to_global_interface_for2(): -> not implemented!\n"); + +} + +// call for 'CUT_BY_INTERFACE' +template +void ParticleMapper::add_local_mat_to_global_interface( + matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd) { +// get data + const int levIndex = get_Index(dd->grid_level(), dd); + int prtIndex = get_prtIndex(); + +/* // Attention: call for 'getprtIndex()'-method of 'InterfaceHandlerLocalParticle', i.e. simply 'get_prtIndex()' + // because: m_spParticleHandlerGlobal->get_prtIndex(-> size_t dof <-) calls 'getprtIndex()'-method of 'CutElementHander', + // which contains an array, which is not allready implemented to be filled during computation!! + // (only necessary for more than 1 particle cutting an element!) + + int prtIndex = m_spParticleHandlerGlobal->get_prtIndex(0); + if (prtIndex == -1) + prtIndex = m_spParticleHandlerGlobal->get_prtIndex(1); + if (prtIndex == -1) + prtIndex = m_spParticleHandlerGlobal->get_prtIndex(2); +*/ + std::vector < DoFIndex > transInd, rotInd; + m_spParticleHandlerGlobal->get_global_indices(transInd, rotInd, levIndex, + prtIndex); + +// A. add mass part to jacobian + if (m_bFlagInertial[prtIndex]) + add_mass_part_jac(mat, transInd, rotInd, levIndex, prtIndex); + +// B. add local to global + if (!UsualAss()) + add_local_mat_to_global_FT(mat, lmat, transInd, rotInd); + //else + // ToDo add_local_mat_to_global_usual(mat, lmat, dd); +} + + + +template +void ParticleMapper::add_glowinski_repulsive_force_rhs(vector_type& vec, + std::vector transInd, std::vector rotInd, + const int levIndex, const int prtIndex) +{ + //UG_LOG("add_repulsive_force \n"); + //////////////////////////////////////////////////////////////// + // compute repulsive force: + //////////////////////////////////////////////////////////////// + + for (size_t i = 0; i < num_particles(); ++i) { + if (i == prtIndex) {continue;} + // Get particle values + MathVector center_i = m_spParticleHandlerGlobal->get_center(i); + MathVector center_prtIndex = m_spParticleHandlerGlobal->get_center(prtIndex); + double Mass_i = Mass(levIndex,i); + double Mass_prtIndex = Mass(levIndex,prtIndex); + + // Calculate distance vector between center points + double dist = 0; + for (size_t d = 0; d < dim; ++d){ + dist += (center_i[d]-center_prtIndex[d])*(center_i[d]-center_prtIndex[d]); + } + dist = sqrt(dist); + MathVector distanceVec = center_prtIndex; + distanceVec -= center_i; + distanceVec /= dist; + + // Calculate force + double force = (Mass_i+Mass_prtIndex)/2*981/(0.5*m_epsilon); + double max1 = std::max(0.0,-(dist-m_spParticleHandlerGlobal->get_radius(i)-m_spParticleHandlerGlobal->get_radius(prtIndex)-m_rho)/(m_rho)); + force *= pow(max1,2); + + // Scale with time step + number timeScale = 1.0; + if (is_time_dependent()) { + timeScale = m_dt; + force *= timeScale; + } + + // UG_LOG("Max/original force is " << force << ".\n"); + + UG_LOG("Unscaled Max/original repulsive force is "< +void ParticleMapper::add_minimum_correction_force_rhs(vector_type& vec, + std::vector transInd, std::vector rotInd, + const int levIndex, const int prtIndex) +{ + //UG_LOG("add_repulsive_force \n"); + //////////////////////////////////////////////////////////////// + // compute repulsive force: + //////////////////////////////////////////////////////////////// + // if (!m_spParticleHandlerGlobal->valid_prt_information(i)) { + // return; + // } + + for (size_t i = 0; i < num_particles(); ++i) { + if (!m_bGlowRepulsiveForce && (i != prtIndex)) { + // Do not calc force with outdated particle informations + + if (i == prtIndex) {continue;} + // Get particle values + MathVector center_i = m_spParticleHandlerGlobal->get_center(i); + MathVector center_prtIndex = m_spParticleHandlerGlobal->get_center(prtIndex); + double Mass_i = Mass(levIndex,i); + double Mass_prtIndex = Mass(levIndex,prtIndex); + + // Calculate distance vector between center points + double dist = 0; + for (size_t d = 0; d < dim; ++d){ + dist += (center_i[d]-center_prtIndex[d])*(center_i[d]-center_prtIndex[d]); + } + dist = sqrt(dist); + MathVector distanceVec = center_prtIndex; + distanceVec -= center_i; + distanceVec /= dist; + if (m_bForceLog) { + if (dim == 2) { + UG_LOG("distanceVec is ("<< distanceVec[0] <<","<< distanceVec[1] <<").\n"); + } else { + UG_LOG("distanceVec is ("<< distanceVec[0] <<","<< distanceVec[1] <<","<< distanceVec[2] <<").\n"); + } + } + + // Calculate force + double force = (Mass_i+Mass_prtIndex)/2*981/(m_epsilon); + double max1 = std::max(0.0,-(dist-m_spParticleHandlerGlobal->get_radius(i)-m_spParticleHandlerGlobal->get_radius(prtIndex)-m_rho)/(m_rho)); + force *= pow(max1,2); + + // Scale with time step + number timeScale = 1.0; + if (is_time_dependent()) { + timeScale = m_dt; + force *= timeScale; + } + + // UG_LOG("Max/original force is " << force << ".\n"); + if (m_bForceLog) { + UG_LOG("Unscaled Max/original repulsive force is "< center_i = m_spParticleHandlerGlobal->get_center(i); + MathVector center_prtIndex = m_spParticleHandlerGlobal->get_center(prtIndex); + double Mass_i = Mass(levIndex,i); + double Mass_prtIndex = Mass(levIndex,prtIndex); + + // Calculate distance vector between center points + double dist = 0; + for (size_t d = 0; d < dim; ++d){ + dist += (center_i[d]-center_prtIndex[d])*(center_i[d]-center_prtIndex[d]); + } + dist = sqrt(dist); + MathVector distanceVec = center_prtIndex; + distanceVec -= center_i; + distanceVec /= dist; + + double Delta_r = m_repulsiveDistance; + double force = Mass_i/(Mass_i+Mass_prtIndex)*Delta_r/2 * 1/(m_dt*m_dt); + // double force = Delta_r/2 * 1/(m_rho*m_rho); + + + // Scale with time step + number timeScale = 1.0; + if (is_time_dependent()) { + timeScale = m_dt; + force *= timeScale; + } + + DoFRef(vec, transInd[0]) -= Mass_prtIndex*force*distanceVec[0]; + DoFRef(vec, transInd[1]) -= Mass_prtIndex*force*distanceVec[1]; + if (dim == 3) + DoFRef(vec, transInd[2]) -= Mass_prtIndex*force*distanceVec[2]; + if (m_bForceLog) { + UG_LOG("Unscaled equivalent repulsive force is "< +void ParticleMapper::add_repulsive_force_rhs(vector_type& vec, + std::vector transInd, std::vector rotInd, + const int levIndex, const int prtIndex) +{ + //UG_LOG("add_repulsive_force \n"); + //////////////////////////////////////////////////////////////// + // compute repulsive force: + //////////////////////////////////////////////////////////////// + + double force = m_repulsiveForce; + + for (size_t i = 0; i < num_particles(); ++i) { + if (i == prtIndex) {continue;} + // Get particle values + MathVector center_i = m_spParticleHandlerGlobal->get_center(i); + MathVector center_prtIndex = m_spParticleHandlerGlobal->get_center(prtIndex); + double Mass_i = Mass(levIndex,i); + double Mass_prtIndex = Mass(levIndex,prtIndex); + + // Calculate distance vector between center points + double dist = 0; + for (size_t d = 0; d < dim; ++d){ + dist += (center_i[d]-center_prtIndex[d])*(center_i[d]-center_prtIndex[d]); + } + dist = sqrt(dist); + MathVector distanceVec = center_prtIndex; + distanceVec -= center_i; + distanceVec /= dist; + + UG_LOG("Unscaled equivalent repulsive force is "< +void ParticleMapper::set_gravitational_rhs(vector_type& vec, + std::vector transInd, std::vector rotInd, + const int levIndex, const int prtIndex) +{ +// some initial checks: Parameters need to be set via lua-script! + if (m_gravityConst == 0.0) + UG_THROW("m_gravityConst not defined!\n"); + if (is_time_dependent() && m_dt == 0.0) + UG_THROW("time step 'm_dt' not defined! Needs to be set via lua-script: 'set_time_step(dt)'...\n"); + + + bool logGravity = true; + + if (logGravity) + { + UG_LOG("//////////////////////////////// - log_Gravity (" << prtIndex << ") - ///////////////////////////////\n"); + + UG_LOG("VORHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); + UG_LOG("VORHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); + if (dim == 3) + UG_LOG("VORHER: defect(trans,2): " << DoFRef(vec, transInd[2]) << "\n"); + + UG_LOG("VORHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); + UG_LOG("VORHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); + if (dim == 3) + UG_LOG("VORHER: defect(rot,2): " << DoFRef(vec, rotInd[2]) << "\n"); + + UG_LOG("m_gravityConst = " << m_gravityConst << "\n"); + + } + + //////////////////////////////////////////////////////////////// + // compute gravitational force to rhs: + //////////////////////////////////////////////////////////////// + + number volume; + if (m_bVolumeCompExact) + volume = Volume(levIndex, prtIndex); + else + volume = compute_volume(levIndex, prtIndex); + + const number gravitationalMass = Mass(levIndex, prtIndex, volume); + + number gravityForce = m_gravityConst * gravitationalMass; + if (dim == 3) + gravityForce = m_gravityConst * gravitationalMass; + + number timeScale = 1.0; + if (is_time_dependent()) + timeScale = m_dt; + + //////////////////////////////////////////////////////////////// + // add gravitational force to rhs: + //////////////////////////////////////////////////////////////// + if (dim == 2) + DoFRef(vec, transInd[0]) -= timeScale * gravityForce; + if (dim == 3) + DoFRef(vec, transInd[2]) -= timeScale * gravityForce; + + + if (logGravity) + { + UG_LOG("gravitationalMass: " << gravitationalMass << "\n"); + + UG_LOG("gravForce added: " << gravityForce << "dt: " << m_dt <<"\n"); + UG_LOG("//////////////////////////////// - log_Gravity - ///////////////////////////////\n"); + UG_LOG("NACHHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); + UG_LOG("NACHHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); + if (dim == 3) + UG_LOG("NACCHHER: defect(trans,2): " << DoFRef(vec, transInd[2]) << "\n"); + + UG_LOG("NACHHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); + UG_LOG("NACHHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); + if (dim == 3) + UG_LOG("NACHHER: defect(rot,2): " << DoFRef(vec, rotInd[2]) << "\n"); + } + +} + +// call for 'OUTSIDE_DOM' +template +void ParticleMapper::map_all_local_vec_to_transDoF( + vector_type& vec, const LocalVector& lvec, + ConstSmartPtr dd) { + +} + +template +void ParticleMapper::add_mass_part_def(vector_type& vec, + std::vector transInd, std::vector rotInd, + const int levIndex, const int prtIndex) { + bool logGravity = false; + + if (logGravity) + UG_LOG( + "//////////////////////////////// - log momentum - ///////////////////////////////\n"); + if (logGravity) + UG_LOG("VORHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); + if (logGravity) + UG_LOG("VORHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); + if (logGravity) + UG_LOG("VORHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); + if (logGravity) + UG_LOG("VORHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); + + number volume; + if (m_bVolumeCompExact) + volume = Volume(levIndex, prtIndex); + else + volume = compute_volume(levIndex, prtIndex); + + const number mass = Mass(levIndex, prtIndex, volume); + const number momOfInertia = MomOfInertia(levIndex, prtIndex, volume); + MathVector < 2 > vScaleMass; + vScaleMass[0] = 1.0; + vScaleMass[1] = -1.0; + +// loop all time points and assemble them + for (int i = 1; i >= 0; --i) { + if (logGravity) + UG_LOG("i = " << i << ":\n"); + for (int d = 0; d < dim; ++d) { + double transSol = m_spParticleHandlerGlobal->get_transSol(prtIndex, + i)[d]; + double rotSol = + m_spParticleHandlerGlobal->get_rotSol(prtIndex, i)[d]; + + if (logGravity) + UG_LOG("transSol(" << i << ") = " << transSol << "\n"); + if (logGravity) + UG_LOG("rotSol(" << i << ") = " << rotSol << "\n"); + + if (logGravity) + UG_LOG( + "+= vScaleMass[" << i << "]*mass*transSol = " << vScaleMass[i]*mass*transSol << "\n"); + if (logGravity) + UG_LOG( + "+= vScaleMass[" << i << "]*momOfInertia*rotSol = " << vScaleMass[i]*momOfInertia*rotSol << "\n"); + + DoFRef(vec, transInd[d]) += vScaleMass[i] * mass * transSol; + if (dim == 3 || d == 0) + DoFRef(vec, rotInd[d]) += vScaleMass[i] * momOfInertia * rotSol; + } + } + + if (logGravity) + UG_LOG("NACHHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); + if (logGravity) + UG_LOG( + "NACCHHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); + if (logGravity) + UG_LOG("NACHHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); + if (logGravity) + UG_LOG("NACHHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); + +// during 'modify_GlobalSol(): m_bFlagInertial := true + if (m_bVolumeCompExact) + m_bFlagInertial[prtIndex] = false; // => call only ONCE + +} + +template +void ParticleMapper::add_rhs(vector_type& vec, + std::vector transInd, std::vector rotInd, + const int levIndex, const int prtIndex) { + + if (m_bFlagGravity[prtIndex]) + set_gravitational_rhs(vec, transInd, rotInd, levIndex, prtIndex); + + if (m_bRepulsiveForce){ + add_repulsive_force_rhs(vec, transInd, rotInd, levIndex, prtIndex); + } + + if (m_bGlowRepulsiveForce){ + add_glowinski_repulsive_force_rhs(vec, transInd, rotInd, levIndex, prtIndex); + } + + // no if here because of calculations and a UG_LOG call inside the function that should be printed everytime. + // if clause is inside the function and force is added only if m_bMaxRepulsiveForce + add_minimum_correction_force_rhs(vec, transInd, rotInd, levIndex, prtIndex); + +// during 'modify_GlobalSol(): m_bFlagGravity := true + + if (m_bVolumeCompExact) + m_bFlagGravity[prtIndex] = false; // => call only ONCE + +} + +// call for 'CUT_BY_2_INTERFACE' +template +void ParticleMapper::add_local_vec_to_global_interface_for2( + vector_type& vec, const LocalVector& lvec, + ConstSmartPtr dd) { + UG_LOG("start add_local_vec_to_global_interface_for2()\n"); +// get data + const int levIndex = get_Index(dd->grid_level(), dd); + std::vector < DoFIndex > transInd1, rotInd1, transInd2, rotInd2; + m_spParticleHandlerGlobal->get_global_indices(transInd1, rotInd1, levIndex, + 0); + m_spParticleHandlerGlobal->get_global_indices(transInd2, rotInd2, levIndex, + 1); + +// A. add local to global + if (!UsualAss()) + if (m_spInterfaceHandlerLocal->StdFV_assembling()) + add_local_vec_to_global_FT_for2_StdFV(vec, lvec, transInd1, rotInd1, + transInd2, rotInd2); + else + add_local_vec_to_global_FT_for2(vec, lvec, transInd1, rotInd1, + transInd2, rotInd2); + else + UG_THROW( + "add_local_vec_to_global_interface_for2(): -> not implemented!\n"); + +} + +// call for 'CUT_BY_INTERFACE' +template +void ParticleMapper::add_local_vec_to_global_interface( + vector_type& vec, const LocalVector& lvec, + ConstSmartPtr dd) { +// get data + const int levIndex = get_Index(dd->grid_level(), dd); + const int prtIndex = get_prtIndex(); + std::vector < DoFIndex > transInd, rotInd; + m_spParticleHandlerGlobal->get_global_indices(transInd, rotInd, levIndex, + prtIndex); + +// A. add local to global + if (!UsualAss()) + add_local_vec_to_global_FT(vec, lvec, transInd, rotInd); + // else + // ToDo add_local_vec_to_global_usual(vec, lvec, dd); + +// B. add mass part to defect + if (m_bFlagInertial[prtIndex]) + add_mass_part_def(vec, transInd, rotInd, levIndex, prtIndex); + +// C. add rhs to defect + if (m_bFlagGravity[prtIndex]) + add_rhs(vec, transInd, rotInd, levIndex, prtIndex); + +} + +/* + template + void ParticleMapper:: + add_local_mat_to_global_FT_for2(matrix_type& mat, const LocalMatrix& lmat, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2) + { + UG_LOG("start add_local_mat_to_global_FT_for2()\n"); + + UG_LOG("transInd1: " << transInd1[0] << "\n"); + UG_LOG("transInd2: " << transInd2[0] << "\n"); + UG_LOG("rotInd1: " << rotInd1[0] << "\n"); + UG_LOG("rotInd2: " << rotInd2[0] << "\n"); + + MathMatrix rotationMatCo, rotationMatIP, rotationMatIP_transposed; + std::vector transInd_from, rotInd_from; + std::vector transInd_to, rotInd_to; + + UG_LOG("lmat.num_all_row_dof(0) = \n" << lmat.num_all_row_dof(0) << "\n"); + UG_LOG("lmat.num_all_row_dof(1) = \n" << lmat.num_all_row_dof(1) << "\n"); + if ( lmat.num_all_row_dof(0) != 4 ) + UG_THROW("lmat.num_all_row_dof(2) = \n" << lmat.num_all_row_dof(2) << "\n"); + + for(size_t fct1=0; fct1 < 2; ++fct1) + for(size_t fct2=0; fct2 < 2; ++fct2) + for(size_t dof1=0; dof1 < 4; ++dof1) + for(size_t dof2=0; dof2 < 4; ++dof2) + { + rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(dof2)); + rotationMatIP = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_ip(dof1)); + + UG_LOG("dof1: " << dof1 << ", m_spInterfaceHandlerLocal->radial_at_ip(dof1): " << m_spInterfaceHandlerLocal->radial_at_ip(dof1) << "\n"); + UG_LOG("dof2: " << dof2 << ", m_spInterfaceHandlerLocal->radial_at_co(dof2): " << m_spInterfaceHandlerLocal->radial_at_co(dof2) << "\n"); + + + // coupling FROM particle1 + if ( dof1 < 2 ) { transInd_from = transInd1; rotInd_from = rotInd1; } + // coupling FROM particle2 + else { transInd_from = transInd2; rotInd_from = rotInd2; } + // coupling TO particle1 + if ( dof2 < 2 ) { transInd_to = transInd1; rotInd_to = rotInd1; } + // coupling TO particle2 + else { transInd_to = transInd2; rotInd_to = rotInd2; } + + UG_LOG("transInd_from: " << transInd_from[0] << "\n"); + UG_LOG("rotInd_from: " << rotInd_from[0] << "\n"); + UG_LOG("transInd_to: " << transInd_to[0] << "\n"); + UG_LOG("rotInd_to: " << rotInd_to[0] << "\n"); + + UG_THROW("check it out...\n"); + + // trans-trans + DoFRef(mat, transInd_from[fct1], transInd_to[fct2]) + += lmat.value(fct1,dof1,fct2,dof2); + + // trans-rot + for ( size_t cmp = 0; cmp < dim; ++cmp ) + DoFRef(mat, transInd_from[fct1], rotInd_to[cmp]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp]; + + // rot-trans + for ( size_t cmp = 0; cmp < dim; ++cmp ) + DoFRef(mat, rotInd_from[cmp], transInd_to[fct2]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatIP[fct1][cmp]; + + // rot-rot + for ( size_t cmp1 = 0; cmp1 < dim; ++cmp1 ) + for ( size_t cmp2 = 0; cmp2 < dim; ++cmp2 ) + DoFRef(mat, rotInd_from[cmp1], rotInd_to[cmp2]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp2]*rotationMatIP[fct1][cmp1]; + + } // end dof2-loop + + + + const LocalIndices& rowInd = lmat.get_row_indices(); + const LocalIndices& colInd = lmat.get_col_indices(); + + } + */ + +template +size_t ParticleMapper::map_for2(size_t dof) { + if (dof == 4) + return m_spInterfaceHandlerLocal->m_vNOInterfaceID[0]; + else if (dof < 2) + return m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]; + else if (dof >= 2) + return m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]; + else + UG_THROW( + "ParticleMapper::map_for2(): error: dof = " << dof << " should lie between 0 and 4!\n"); + +} + +template +void ParticleMapper::add_local_mat_to_global_FT_for2_StdFV( + matrix_type& mat, const LocalMatrix& lmat, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2) { + UG_LOG("----- START add_local_mat_to_global_FT_for2_StdFV()\n"); + + MathMatrix rotationMatCo, rotationMatIP, rotationMatIP_transposed; + MathVector radialVector; + + const LocalIndices& rowInd = lmat.get_row_indices(); + const LocalIndices& colInd = lmat.get_col_indices(); + + bool remap = true; + + for (size_t fct1 = 0; fct1 < lmat.num_all_row_fct(); ++fct1) + for (size_t dof1 = 0; dof1 < lmat.num_all_row_dof(fct1); ++dof1) { + size_t _dof1 = dof1; + if (remap) + _dof1 = m_spInterfaceHandlerLocal->corner_orig(dof1); + const DoFIndex indexRow = DoFIndex(rowInd.index(fct1, _dof1), + rowInd.comp(fct1, _dof1)); + + UG_LOG("fct1 " << fct1 << "_dof1 " << _dof1 << "\n"); + + if (indexRow[0] == 15) { + UG_LOG( + "rowInd.index(fct1,_dof1) = " << rowInd.index(fct1,_dof1) << "\n"); + } else { + UG_LOG("indexRow[0] = " << indexRow[0] << "\n"); + } + + if (indexRow[0] == 1 && dof1 != 2) + UG_THROW("aha...dof1 = " << dof1 << "\n"); + + for (size_t fct2 = 0; fct2 < lmat.num_all_col_fct(); ++fct2) + for (size_t dof2 = 0; dof2 < lmat.num_all_col_dof(fct2); + ++dof2) { + size_t _dof2 = dof2; + if (remap) + _dof2 = m_spInterfaceHandlerLocal->corner_orig(dof2); + const DoFIndex indexCol = DoFIndex( + colInd.index(fct2, _dof2), + colInd.comp(fct2, _dof2)); + + if (indexRow[0] == 15 && indexCol[0] == 17) + UG_LOG("cut by 2??\n"); + + size_t modus = getMappingModus(fct1, _dof1, fct2, _dof2); + + rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_co(dof2)); + rotationMatIP = m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_ip(dof1)); + + const int prtIndex1 = getPrtIndex(_dof1); + const int prtIndex2 = getPrtIndex(_dof2); + + switch (modus) { + case 0: { + DoFRef(mat, indexRow, indexCol) += lmat.value(fct1, + dof1, fct2, dof2); + } + break; + case 1: { + std::vector < DoFIndex > transInd_to, rotInd_to; + // coupling TO particle1 + if (prtIndex2 == 0) { + transInd_to = transInd1; + rotInd_to = rotInd1; + } + // coupling TO particle2 + else { + transInd_to = transInd2; + rotInd_to = rotInd2; + } + + DoFRef(mat, indexRow, transInd_to[fct2]) += lmat.value( + fct1, dof1, fct2, dof2); + + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, indexRow, rotInd_to[cmp]) += lmat.value( + fct1, dof1, fct2, dof2) + * rotationMatCo[fct2][cmp]; + + } + break; + case 2: { + std::vector < DoFIndex > transInd_from, rotInd_from; + // coupling FROM particle1 + if (prtIndex1 == 0) { + transInd_from = transInd1; + rotInd_from = rotInd1; + } + // coupling FROM particle2 + else { + transInd_from = transInd2; + rotInd_from = rotInd2; + } + + DoFRef(mat, transInd_from[fct1], indexCol) += + lmat.value(fct1, dof1, fct2, dof2); + + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, rotInd_from[cmp], indexCol) += + lmat.value(fct1, dof1, fct2, dof2) + * rotationMatIP[fct1][cmp]; + + } + break; + case 3: { + std::vector < DoFIndex > transInd_from, rotInd_from; + std::vector < DoFIndex > transInd_to, rotInd_to; + // coupling TO particle1 + if (prtIndex2 == 0) { + transInd_to = transInd1; + rotInd_to = rotInd1; + } + // coupling TO particle2 + else { + transInd_to = transInd2; + rotInd_to = rotInd2; + } + + // coupling FROM particle1 + if (prtIndex1 == 0) { + transInd_from = transInd1; + rotInd_from = rotInd1; + } + // coupling FROM particle2 + else { + transInd_from = transInd2; + rotInd_from = rotInd2; + } + + // trans-trans + DoFRef(mat, transInd_from[fct1], transInd_to[fct2]) += + lmat.value(fct1, dof1, fct2, dof2); + + // trans-rot ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, transInd_from[fct1], rotInd_to[cmp]) += + lmat.value(fct1, dof1, fct2, dof2) + * rotationMatCo[fct2][cmp]; + + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, rotInd_from[cmp], transInd_to[fct2]) += + lmat.value(fct1, dof1, fct2, dof2) + * rotationMatIP[fct1][cmp]; + + for (size_t cmp1 = 0; cmp1 < dim; ++cmp1) + for (size_t cmp2 = 0; cmp2 < dim; ++cmp2) + DoFRef(mat, rotInd_from[cmp1], rotInd_to[cmp2]) += + lmat.value(fct1, dof1, fct2, dof2) + * rotationMatCo[fct2][cmp2] + * rotationMatIP[fct1][cmp1]; + + } + break; + case 4: { // to pressure outside: sum = e-20 => skip! + } + break; + + default: + throw(UGError("Error in LocToGlob!")); + + } // end switch-cases + + } // end dof2-loop + + } + UG_LOG("----- END add_local_mat_to_global_FT_for2_StdFV()\n"); + +} + +template +void ParticleMapper::add_local_mat_to_global_FT_for2( + matrix_type& mat, const LocalMatrix& lmat, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2) { + UG_LOG("--- START add_local_mat_to_global_FT_for2()\n"); + + MathMatrix rotationMatCo, rotationMatIP, rotationMatIP_transposed; + MathVector radialVector; + + const LocalIndices& rowInd = lmat.get_row_indices(); + const LocalIndices& colInd = lmat.get_col_indices(); + + for (size_t fct1 = 0; fct1 < lmat.num_all_row_fct(); ++fct1) + for (size_t dof1 = 0; dof1 < lmat.num_all_row_dof(fct1); ++dof1) { + const size_t dofMap1 = map_for2(dof1); + const DoFIndex indexRow = DoFIndex(rowInd.index(fct1, dofMap1), + rowInd.comp(fct1, dofMap1)); + + for (size_t fct2 = 0; fct2 < lmat.num_all_col_fct(); ++fct2) + for (size_t dof2 = 0; dof2 < lmat.num_all_col_dof(fct2); + ++dof2) { + const size_t dofMap2 = map_for2(dof2); + const DoFIndex indexCol = DoFIndex( + colInd.index(fct2, dofMap2), + colInd.comp(fct2, dofMap2)); + + UG_LOG("dof1: " << dof1 << ", dofMap1: " << dofMap1 << "\n"); + UG_LOG("dof2: " << dof2 << ", dofMap2: " << dofMap2 << "\n"); + + rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_co(dof2)); + rotationMatIP = m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_ip(dof1)); + + UG_LOG( + "dof1: " << dof1 << ", m_spInterfaceHandlerLocal->radial_at_ip(dof1): " << m_spInterfaceHandlerLocal->radial_at_ip(dof1) << "\n"); + UG_LOG( + "dof2: " << dof2 << ", m_spInterfaceHandlerLocal->radial_at_co(dof2): " << m_spInterfaceHandlerLocal->radial_at_co(dof2) << "\n"); + + size_t modus = getMappingModus_for2(fct1, dof1, fct2, dof2); + + switch (modus) { + case 0: { + DoFRef(mat, indexRow, indexCol) += lmat.value(fct1, + dof1, fct2, dof2); + } + break; + case 1: { + std::vector < DoFIndex > transInd_to, rotInd_to; + // coupling TO particle1 + if (dof2 < 2) { + transInd_to = transInd1; + rotInd_to = rotInd1; + } + // coupling TO particle2 + else { + transInd_to = transInd2; + rotInd_to = rotInd2; + } + UG_LOG("transInd_to: " << transInd_to[0] << "\n"); + UG_LOG("rotInd_to: " << rotInd_to[0] << "\n"); + + DoFRef(mat, indexRow, transInd_to[fct2]) += lmat.value( + fct1, dof1, fct2, dof2); + + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, indexRow, rotInd_to[cmp]) += lmat.value( + fct1, dof1, fct2, dof2) + * rotationMatCo[fct2][cmp]; + + } + break; + case 2: { + std::vector < DoFIndex > transInd_from, rotInd_from; + // coupling FROM particle1 + if (dof1 < 2) { + transInd_from = transInd1; + rotInd_from = rotInd1; + } + // coupling FROM particle2 + else { + transInd_from = transInd2; + rotInd_from = rotInd2; + } + UG_LOG("transInd_from: " << transInd_from[0] << "\n"); + UG_LOG("rotInd_from: " << rotInd_from[0] << "\n"); + + DoFRef(mat, transInd_from[fct1], indexCol) += + lmat.value(fct1, dof1, fct2, dof2); + + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, rotInd_from[cmp], indexCol) += + lmat.value(fct1, dof1, fct2, dof2) + * rotationMatIP[fct1][cmp]; + + } + break; + case 3: { + std::vector < DoFIndex > transInd_from, rotInd_from; + std::vector < DoFIndex > transInd_to, rotInd_to; + // coupling TO particle1 + if (dof2 < 2) { + transInd_to = transInd1; + rotInd_to = rotInd1; + } + // coupling TO particle2 + else { + transInd_to = transInd2; + rotInd_to = rotInd2; + } + UG_LOG("transInd_to: " << transInd_to[0] << "\n"); + UG_LOG("rotInd_to: " << rotInd_to[0] << "\n"); + + // coupling FROM particle1 + if (dof1 < 2) { + transInd_from = transInd1; + rotInd_from = rotInd1; + } + // coupling FROM particle2 + else { + transInd_from = transInd2; + rotInd_from = rotInd2; + } + UG_LOG("transInd_from: " << transInd_from[0] << "\n"); + UG_LOG("rotInd_from: " << rotInd_from[0] << "\n"); + + // trans-trans + DoFRef(mat, transInd_from[fct1], transInd_to[fct2]) += + lmat.value(fct1, dof1, fct2, dof2); + + // trans-rot ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, transInd_from[fct1], rotInd_to[cmp]) += + lmat.value(fct1, dof1, fct2, dof2) + * rotationMatCo[fct2][cmp]; + + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, rotInd_from[cmp], transInd_to[fct2]) += + lmat.value(fct1, dof1, fct2, dof2) + * rotationMatIP[fct1][cmp]; + + for (size_t cmp1 = 0; cmp1 < dim; ++cmp1) + for (size_t cmp2 = 0; cmp2 < dim; ++cmp2) + DoFRef(mat, rotInd_from[cmp1], rotInd_to[cmp2]) += + lmat.value(fct1, dof1, fct2, dof2) + * rotationMatCo[fct2][cmp2] + * rotationMatIP[fct1][cmp1]; + + } + break; + case 4: { // to pressure outside: sum = e-20 => skip! + } + break; + + default: + throw(UGError("Error in LocToGlob!")); + + } // end switch-cases + + } // end dof2-loop + + //////////////////////////////////////////////////////////////////////////////////////////////// + // finally set dirichlet row for velocity DoFs on interface: + // ---> also done during 'set_identity_mat_constraint()', BUT only for OUTSIDE_DOM-elements!! + //////////////////////////////////////////////////////////////////////////////////////////////// + + // dof1 != 4 => DoF lies on an interface of one of the two particles + if (dof1 != 4) { + const size_t indexDiagInd = rowInd.index(0, dofMap1); + if (indexDiagInd != transInd1[0][0] + && indexDiagInd != rotInd1[0][0] + && indexDiagInd != transInd2[0][0] + && indexDiagInd != rotInd2[0][0]) { + for (size_t d = 0; d < dim; ++d) { + const DoFIndex indexDiag = DoFIndex( + rowInd.index(d, dofMap1), + rowInd.comp(d, dofMap1)); + DoFRef(mat, indexDiag, indexDiag) = 1.0; + } + } + } + } // end dof1-loop + + if (0) // m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) + UG_THROW("check it out...\n"); + UG_LOG("--- END add_local_mat_to_global_FT_for2()\n"); + +} + +template +void ParticleMapper::add_local_mat_to_global_FT( + matrix_type& mat, const LocalMatrix& lmat, + std::vector transInd, std::vector rotInd) { + bool bOld = true; + bool remap = true; + + bool transposed = false; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // VORSICHT: lmat hat algebra-struktur und groesse von m_locJ, also potentiell groesser, wenn quadrilateral!! + // ABER: ENTHAELT an alten indices noch originale global-index-Info: + // lmat haelt sich eigenen LocalIndices-member: lmat.m_pRowIndex, lmat.m_pColIndex + // mit lmat.resize(ind) = lmat.resize(ind,ind) => lmat.m_pRowIndex = ind, lmat.m_pColIndex = ind + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + LocalMatrix locMatOrig = lmat; + LocalMatrix locMatTrans = lmat; + LocalMatrix locMatRot = lmat; + locMatOrig = 0.0; + locMatTrans = 0.0; + locMatRot = 0.0; + +// cutElem = true: => re-associate to trans/rot-DoFs + //////////////////////////////////////////////////////////////////////////////////////////////////// + // for LocToGLob-mapping only the following geo-data are needed: + // geo.vOriginalCornerID, geo.vInterfaceID, geo.m_bUseOriginalCornerRadial, + // geo.m_vRadialAtCo, geo.m_vRadialAtIP + // + // => no scfv-data, but radial info: + // This can be handled USING ONLY geo_IB: + // - case 1 => PrsGeom; case 2/3 => IBGeom; + // - case 1 => geo_Prs.m_vRadialAtCo == geo_IB.m_vRadialAtCo :-) + // + // => usage of ONLY geo_IB-data possible, since all needed data is identic wit geo_Prs:-) + //////////////////////////////////////////////////////////////////////////////////////////////////// + + MathMatrix rotationMatCo, rotationMatIP; + MathVector radialVector; + + const LocalIndices& rowInd = lmat.get_row_indices(); + const LocalIndices& colInd = lmat.get_col_indices(); + + + const int prtIndex = get_prtIndex(); + + if (prtIndex == -1) + UG_THROW( + "ParticleMapper::add_local_mat_to_global_FT(): prtIndex invalid!: prtIndex = " << prtIndex << "\n"); + + for (size_t fct1 = 0; fct1 < lmat.num_all_row_fct(); ++fct1) + for (size_t dof1 = 0; dof1 < lmat.num_all_row_dof(fct1); ++dof1) { + size_t _dof1 = dof1; + if (remap) + _dof1 = m_spInterfaceHandlerLocal->corner_orig(dof1); + + const DoFIndex indexRow = DoFIndex(rowInd.index(fct1, _dof1), + rowInd.comp(fct1, _dof1)); + + if (indexRow[0] == 0) { + UG_LOG( + "rowInd.index(fct1,_dof1) = " << rowInd.index(fct1,_dof1) << "\n"); + } + + for (size_t fct2 = 0; fct2 < lmat.num_all_col_fct(); ++fct2) + for (size_t dof2 = 0; dof2 < lmat.num_all_col_dof(fct2); + ++dof2) { + + size_t _dof2 = dof2; + if (remap) + _dof2 = m_spInterfaceHandlerLocal->corner_orig(dof2); + const DoFIndex indexCol = DoFIndex( + colInd.index(fct2, _dof2), + colInd.comp(fct2, _dof2)); + + if (indexRow[0] == 15 && indexCol[0] == 17) + UG_LOG("cut by 2??\n"); + + size_t modus = getMappingModus(fct1, _dof1, fct2, _dof2); + if (1) //ToDo? m_spInterfaceHandlerLocal->m_bUseOriginalCornerRadial ) + { + rotationMatCo = + m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_co( + dof2)); + rotationMatIP = + m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_ip( + dof1)); + } else { + rotationMatCo = + m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_co( + dof2)); + rotationMatIP = + m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_ip( + dof1)); + } + + MathMatrix rotationMatIP_transposed; + Transpose(rotationMatIP_transposed, rotationMatIP); + + switch (modus) { + case 0: { + DoFRef(mat, indexRow, indexCol) += lmat.value(fct1, + dof1, fct2, dof2); + } + break; + case 1: { + DoFRef(mat, indexRow, transInd[fct2]) += lmat.value( + fct1, dof1, fct2, dof2); + + for (size_t cmp = 0; cmp < dim; ++cmp) { + DoFRef(mat, indexRow, rotInd[cmp]) += lmat.value( + fct1, dof1, fct2, dof2) + * rotationMatCo[fct2][cmp]; + } + + } + break; + case 2: { + if (!m_spParticleHandlerGlobal->get_DoF_modus_linear( + prtIndex)) + DoFRef(mat, transInd[fct1], indexCol) += lmat.value( + fct1, dof1, fct2, dof2); + + // NOT ONLY assemble particle->velFluid, even IF \int (r x p*n) = 0 + // fct2 == dim NOTWENDIG, da im Fall von irregulaeren Gittern der Defekt sonst inkonsistent werden KANN + // -> getestet mit 'ExactSol_FT.lua' und 'grids/unit_square_tri_irregular_2x2_4_Boundaries.ugx' + for (size_t cmp = 0; cmp < dim; ++cmp) { + //const DoFIndex tmp_indexCol = DoFIndex(colInd.index(cmp,_dof2), colInd.comp(cmp,_dof2)); + if (transposed) { + if (!m_spParticleHandlerGlobal->get_DoF_modus_angular( + prtIndex)) + DoFRef(mat, rotInd[cmp], indexCol) += + lmat.value(fct1, dof1, fct2, dof2) + * rotationMatIP[cmp][fct1]; + } else { + if (1) //fct2 != dim ) + { + if (!m_spParticleHandlerGlobal->get_DoF_modus_angular( + prtIndex)) + DoFRef(mat, rotInd[cmp], indexCol) += + lmat.value(fct1, dof1, fct2, + dof2) + * rotationMatIP[fct1][cmp]; + } + } + + } + + } + break; + case 3: { + + if (!m_spParticleHandlerGlobal->get_DoF_modus_linear( + prtIndex)) { + + // trans-trans + DoFRef(mat, transInd[fct1], transInd[fct2]) += + lmat.value(fct1, dof1, fct2, dof2); + + // trans-rot ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, transInd[fct1], rotInd[cmp]) += + lmat.value(fct1, dof1, fct2, dof2) + * rotationMatCo[fct2][cmp]; + } + + if (!m_spParticleHandlerGlobal->get_DoF_modus_angular( + prtIndex)) { + if (bOld) { + if (transposed) { + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, rotInd[cmp], transInd[fct2]) += + lmat.value(fct1, dof1, fct2, + dof2) + * rotationMatIP[cmp][fct1]; + } else { + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(mat, rotInd[cmp], transInd[fct2]) += + lmat.value(fct1, dof1, fct2, + dof2) + * rotationMatIP[fct1][cmp]; + } + + // rot-rot ( r x (w x r) = r_ip x (w x r_co) = R_ip*R_co^T*w = (R_co*R_ip^T)^T*w) ; ) (...^T*w <=> [fct1][cmp]) + // ToDo: statt (R_co*R_ip^T)^T*w) und [fct1][cmp]: R_ip*R_co^T und [cmp][fct1] + //R^T * R = (r_1)^2 + (r_2)2 + /* number r1 = geo.m_vRadialAtIP[dof1][0]*geo.m_vRadialAtCo[dof2][0]; + number r2 = geo.m_vRadialAtIP[dof1][1]*geo.m_vRadialAtCo[dof2][1]; + number dist_IP = r1 + r2; + DoFRef(mat, rotInd[0], rotInd[0]) + += lmat.value(fct1,dof1,fct2,dof2)*dist_IP; + */ + if (transposed) { + for (size_t cmp1 = 0; cmp1 < dim; ++cmp1) + for (size_t cmp2 = 0; cmp2 < dim; + ++cmp2) + DoFRef(mat, rotInd[cmp1], + rotInd[cmp2]) += lmat.value( + fct1, dof1, fct2, dof2) + * rotationMatCo[fct2][cmp2] + * rotationMatIP[cmp1][fct1]; + } else { + for (size_t cmp1 = 0; cmp1 < dim; ++cmp1) + for (size_t cmp2 = 0; cmp2 < dim; + ++cmp2) + DoFRef(mat, rotInd[cmp1], + rotInd[cmp2]) += lmat.value( + fct1, dof1, fct2, dof2) + * rotationMatCo[fct2][cmp2] + * rotationMatIP[fct1][cmp1]; + } + } else { + DoFRef(mat, rotInd[fct1], transInd[fct2]) += + get_rotJ_ind(fct1, dof1, fct2, dof2); + DoFRef(mat, rotInd[fct1], rotInd[fct2]) += + get_rotJ_rot(fct1, dof1, fct2, dof2); + } + } // end if (...DoF_modus_angular()) + + } + break; + case 4: { // to pressure outside: sum = e-20 => skip! + } + break; + + default: + throw(UGError("Error in LocToGlob!")); + + } // end switch-cases + + } // end dof2-loop + + //////////////////////////////////////////////////////////////////////////////////////////////// + // finally set dirichlet row for velocity DoFs on interface: + // ---> also done during 'set_identity_mat_constraint()', BUT only for OUTSIDE_DOM-elements!! + //////////////////////////////////////////////////////////////////////////////////////////////// + + bool bSetDirichletRowsForVelocity = + m_spInterfaceHandlerLocal->remapped_fromInterface(_dof1); + if (bSetDirichletRowsForVelocity) { + const size_t indexDiagInd = rowInd.index(0, _dof1); + if (indexDiagInd != transInd[0][0] + && indexDiagInd != rotInd[0][0]) { + for (size_t d = 0; d < dim; ++d) { + const DoFIndex indexDiag = DoFIndex( + rowInd.index(d, _dof1), rowInd.comp(d, _dof1)); + DoFRef(mat, indexDiag, indexDiag) = 1.0; + } + } else //if transInd or rotInd lie on cut element and are given by the user, i.e. NO DoFs! + { + // set dirichlet row for translation vel + if (m_spParticleHandlerGlobal->get_DoF_modus_linear( + prtIndex)) { + for (size_t d = 0; d < dim; ++d) { + const DoFIndex indexDiag = DoFIndex( + rowInd.index(d, _dof1), + rowInd.comp(d, _dof1)); + DoFRef(mat, indexDiag, indexDiag) = 1.0; + } + } + // set dirichlet row for rotation vel + if (m_spParticleHandlerGlobal->get_DoF_modus_angular( + prtIndex)) { + for (size_t d = 0; d < dim; ++d) { + const DoFIndex indexDiag = DoFIndex( + rowInd.index(d, _dof1), + rowInd.comp(d, _dof1)); + DoFRef(mat, indexDiag, indexDiag) = 1.0; + } + } + } + } + } // end dof1-loop + +} + +template +void ParticleMapper::assemble_QuadriCorners(vector_type& vec, + const LocalVector& lvec, std::vector transInd1, + std::vector rotInd1, std::vector transInd2, + std::vector rotInd2) { + return; + if (dim == 3) + UG_THROW("in 'assemble_QuadriCorners()': not implemented!\n"); + + UG_LOG("\n start assemble_fluid_nodes()\n"); + UG_LOG("transInd1: " << transInd1[0] << "transInd2: " << transInd2[0] << "\n"); + UG_LOG("rotInd1: " << rotInd1[0] << "rotInd2: " << rotInd2[0] << "\n"); + + bool remap = true; + + for (size_t fct = 0; fct < lvec.num_all_fct(); ++fct) { + for (size_t dof = 0; dof < lvec.num_all_dof(fct); ++dof) { + if (lvec.value(fct, dof) != lvec.value(fct, dof)) + UG_THROW("NAN in 'add_local_vec_to_global_FT()'!...\n"); + + size_t _dof = dof; + if (remap) + _dof = m_spInterfaceHandlerLocal->corner_orig(dof); + + + DoFRef(vec, transInd1[fct]) += lvec.value(fct, dof); + + MathVector RotVec; + RotVec[0] = -m_spInterfaceHandlerLocal->radial_at_ip(dof)[1]; + RotVec[1] = m_spInterfaceHandlerLocal->radial_at_ip(dof)[0]; + + DoFRef(vec, rotInd1[0]) += lvec.value(fct, dof) * RotVec[fct]; + + } // end dof-loop + } + + UG_THROW(" end assemble_QuadriCorners()\n\n"); + +} + +template +void ParticleMapper::assemble_fluid_nodes(vector_type& vec, + const LocalVector& lvec) { + UG_LOG("\n start assemble_fluid_nodes()\n"); + +} + +template +void ParticleMapper::add_local_vec_to_global_FT_for2_StdFV( + vector_type& vec, const LocalVector& lvec, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2) { + if (dim == 3) + UG_THROW( + "add_local_vec_to_global_FT_for2_StdFV() not implemented for 3d!!!\n"); + + bool remap = true; + + UG_LOG("start add_local_vec_to_gloabal_FT_for2_StdFV()\n"); + + const LocalIndices& ind = lvec.get_indices(); + + for (size_t fct = 0; fct < lvec.num_all_fct(); ++fct) + for (size_t dof = 0; dof < lvec.num_all_dof(fct); ++dof) { + if (lvec.value(fct, dof) != lvec.value(fct, dof)) + UG_THROW("NAN in 'add_local_vec_to_global_FT()'!...\n"); + if (lvec.value(fct, dof) > 1e+10) + UG_THROW( + "-----------------------> 1e+10: " << lvec.value(fct,dof) << "\n"); + + size_t _dof = dof; + if (remap) + _dof = m_spInterfaceHandlerLocal->corner_orig(dof); + + const DoFIndex multi_index = DoFIndex(ind.index(fct, _dof), + ind.comp(fct, _dof)); + + UG_LOG("dof: " << dof << ", _dof: " << _dof << "\n"); + UG_LOG("fct: " << fct << "\n"); + + const int prtIndex = getPrtIndex(_dof); + + UG_LOG("nach 'getPrtIndex(dof)': prtIndex = " << prtIndex << "\n"); + + bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface( + _dof); + + // usual assembling for fluid-dof and pressure-fct + if (!isPrtNode || fct == dim) { + DoFRef(vec, multi_index) += lvec.value(fct, dof); + UG_LOG( + "added for fct = " << fct << ", dof = " << dof << ": " << lvec.value(fct,dof) << "\n"); + } else { + MathVector RotVec; + RotVec[0] = -m_spInterfaceHandlerLocal->radial_at_ip(dof)[1]; + RotVec[1] = m_spInterfaceHandlerLocal->radial_at_ip(dof)[0]; + + UG_LOG( + "dof: " << dof << ", m_spInterfaceHandlerLocal->radial_at_ip(dof): " << m_spInterfaceHandlerLocal->radial_at_ip(dof) << "\n"); + + DoFIndex transInd, rotInd; + + if (prtIndex == 0) { + transInd = transInd1[fct]; + rotInd = rotInd1[0]; + UG_LOG( + "transInd1[" << fct << "] = " << transInd1[fct] << "\n"); + } else { + if (prtIndex != 1) + UG_THROW("prtIndex = " << prtIndex << "\n"); + transInd = transInd2[fct]; + rotInd = rotInd2[0]; + UG_LOG( + "transInd2[" << fct << "] = " << transInd2[fct] << "\n"); + } + // finally add connection between the 2 particles: + DoFRef(vec, transInd) += lvec.value(fct, dof); + DoFRef(vec, rotInd) += lvec.value(fct, dof) * RotVec[fct]; + + UG_LOG( + "----> added for fct = " << fct << ", dof = " << dof << ": " << lvec.value(fct,dof) << "\n"); + UG_LOG("RotVec = " << RotVec[fct] << "\n"); + } + + } + + UG_LOG("end add_local_vec_to_gloabal_FT_for2_StdFV()\n\n"); + +} + +template +void ParticleMapper::add_local_vec_to_global_FT_for2( + vector_type& vec, const LocalVector& lvec, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2) { + UG_LOG("start add_local_vec_to_gloabal_FT_for2()\n"); + + const LocalIndices& ind = lvec.get_indices(); + + for (size_t fct = 0; fct < lvec.num_all_fct(); ++fct) + for (size_t dof = 0; dof < lvec.num_all_dof(fct); ++dof) { + if (lvec.value(fct, dof) != lvec.value(fct, dof)) + UG_THROW("NAN in 'add_local_vec_to_global_FT()'!...\n"); + + const size_t dofMap = map_for2(dof); + const DoFIndex multi_index = DoFIndex(ind.index(fct, dofMap), + ind.comp(fct, dofMap)); + + UG_LOG("dof: " << dof << ", dofMap: " << dofMap << "\n"); + UG_LOG("fct: " << fct << "\n"); + + // usual assembling for fluid-dof and pressure-fct + if (dof == 4 || fct == dim) { + DoFRef(vec, multi_index) += lvec.value(fct, dof); + UG_LOG( + "added for fct = " << fct << ", dof = " << dof << ": " << lvec.value(fct,dof) << "\n"); + } else { + + MathVector RotVec; + RotVec[0] = -m_spInterfaceHandlerLocal->radial_at_ip(dof)[1]; + RotVec[1] = m_spInterfaceHandlerLocal->radial_at_ip(dof)[0]; + + UG_LOG( + "dof: " << dof << ", m_spInterfaceHandlerLocal->radial_at_ip(dof): " << m_spInterfaceHandlerLocal->radial_at_ip(dof) << "\n"); + + DoFIndex transInd, rotInd; + + if (dof < 2) { + transInd = transInd1[fct]; + rotInd = rotInd1[0]; + UG_LOG( + "transInd1[" << fct << "] = " << transInd1[fct] << "\n"); + } else { + transInd = transInd2[fct]; + rotInd = rotInd2[0]; + UG_LOG( + "transInd2[" << fct << "] = " << transInd2[fct] << "\n"); + } + // finally add connection between the 2 particles: + DoFRef(vec, transInd) += lvec.value(fct, dof); + DoFRef(vec, rotInd) += lvec.value(fct, dof) * RotVec[fct]; + + UG_LOG( + "----> added for fct = " << fct << ", dof = " << dof << ": " << lvec.value(fct,dof) << "\n"); + UG_LOG("RotVec = " << RotVec[fct] << "\n"); + } + + } + + if (1) //m_spInterfaceHandlerLocal->interface_id_all().size() == 4 ) + UG_LOG("end add_local_vec_to_gloabal_FT_for2()\n\n"); + +} + +template +void ParticleMapper::add_local_vec_to_global_FT( + vector_type& vec, const LocalVector& lvec, + std::vector transInd, std::vector rotInd) +{ + const LocalIndices& ind = lvec.get_indices(); + + bool remap = true; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // VORSICHT: lmat hat algebra-struktur und groesse von m_locJ, also potentiell groesser, wenn quadrilateral!! + // ABER: ENTHAELT an alten indices noch originale global-index-Info: + // lmat haelt sich eigenen LocalIndices-member: lmat.m_pRowIndex, lmat.m_pColIndex + // mit lmat.resize(ind) = lmat.resize(ind,ind) => lmat.m_pRowIndex = ind, lmat.m_pColIndex = ind + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + LocalVector locMatOrig = lvec; + LocalVector locMatTrans = lvec; + LocalVector locMatRot = lvec; + locMatOrig = 0.0; + locMatTrans = 0.0; + locMatRot = 0.0; + + const int prtIndex = get_prtIndex(); + if (prtIndex == -1) + UG_THROW( + "ParticleMapper::add_local_mat_to_global_FT(): prtIndex invalid!: prtIndex = " << prtIndex << "\n"); + + for (size_t fct = 0; fct < lvec.num_all_fct(); ++fct) { + for (size_t dof = 0; dof < lvec.num_all_dof(fct); ++dof) { + if (lvec.value(fct, dof) != lvec.value(fct, dof)) + UG_THROW("NAN in 'add_local_vec_to_global_FT()'!...\n"); + + if (lvec.value(fct, dof) > 1e+10) + UG_THROW("-----------------------> 1e+10: " << lvec.value(fct,dof) << "\n"); + + size_t _dof = dof; + if (remap) + _dof = m_spInterfaceHandlerLocal->corner_orig(dof); + + const DoFIndex multi_index = DoFIndex(ind.index(fct, _dof), + ind.comp(fct, _dof)); +// const DoFIndex _multi_index = DoFIndex(ind.index(fct, dof), +// ind.comp(fct, dof)); + + bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface( + _dof); + + // usual assembling for fluid-dof and pressure-fct + if (!isPrtNode || fct == dim) { + DoFRef(vec, multi_index) += lvec.value(fct, dof); + } + + if (!isPrtNode || fct == dim) { + // do nothing... + } else { + + if (!m_spParticleHandlerGlobal->get_DoF_modus_linear(prtIndex)) + DoFRef(vec, transInd[fct]) += lvec.value(fct, dof); + + if (!m_spParticleHandlerGlobal->get_DoF_modus_angular( + prtIndex)) { + MathVector RotVec; + + if (dim == 2) { + RotVec[0] = -m_spInterfaceHandlerLocal->radial_at_ip( + dof)[1]; + RotVec[1] = + m_spInterfaceHandlerLocal->radial_at_ip(dof)[0]; + } + MathMatrix rotationMatCo, rotationMatIP; + MathMatrix rotationMatIP_transposed; + if (dim == 3) { + rotationMatIP = + m_spParticleHandlerGlobal->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_ip( + dof)); + Transpose(rotationMatIP_transposed, rotationMatIP); + } + MathVector Pos; + Pos[0] = m_spInterfaceHandlerLocal->radial_at_ip(dof)[0]; + Pos[1] = m_spInterfaceHandlerLocal->radial_at_ip(dof)[1]; + + if (dim == 2) + DoFRef(vec, rotInd[0]) += lvec.value(fct, dof) + * RotVec[fct]; + // DoFRef(vec, rotInd[0]) += sqrt(lvec.value(fct,dof)*RotVec[fct]*lvec.value(fct,dof)*RotVec[fct]); + if (dim == 3) + + for (size_t cmp = 0; cmp < dim; ++cmp) + DoFRef(vec, rotInd[cmp]) += lvec.value(fct, dof) + * rotationMatIP_transposed[cmp][fct]; + } // end if (...DoF_modus_angular() ) + } + + } // end dof-loop + } + +} + + + +} // end namespace NavierStokes +} // end namespace ug + +#endif /* PARTICLE_MAPPER_IMPL_H_ */ diff --git a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_tools.h b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_tools.h new file mode 100644 index 0000000..048998c --- /dev/null +++ b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_tools.h @@ -0,0 +1,330 @@ +/* + * moving_particle_tools.h + * + * Created on: 20.01.2015 + * Author: suze + */ + +#ifndef PARTICLE_MAPPER_TOOLS_H_ +#define PARTICLE_MAPPER_TOOLS_H_ + +namespace ug{ +namespace NavierStokes{ + +/* +template +void ParticleMapper:: +add_local_mat_to_global_usual(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd) +{ +// get level index for 'isFluidDoF()' - level dependent! + const int Index = m_myParticle->get_Index(dd->grid_level()); + + PROFILE_FUNC(); + + + const LocalIndices& rowInd = lmat.get_row_indices(); + const LocalIndices& colInd = lmat.get_col_indices(); + + + // index of particle, the element is associated to + int prtIndex, prtIndex_ref = -1; + size_t indexList1; // indexList1 = entry in 'm_vvvIndexRadialPair_List', see 'is_marked()' + // indexList2 = entry in 'm_vvvIndexPosPair_List2', see 'is_borderFluid()' + + bool cutElem = false; + cutElem = elemIsCut(rowInd, lmat.num_all_row_dof(0), Index, &prtIndex, dd); + + for(size_t fct1=0; fct1 < lmat.num_all_row_fct(); ++fct1) + { + // scv-loop: + for(size_t dof1=0; dof1 < lmat.num_all_row_dof(fct1); ++dof1) + { + + const size_t rowIndex = rowInd.index(fct1,dof1); + const size_t rowComp = rowInd.comp(fct1,dof1); + + DoFIndex multi_index_row = DoFIndex(rowIndex, rowComp); + + // if the corresponding DoF is 'inside the fluid' OR 'pressure-DoF': + /////////////////////////////////////////////////////////// + // REMARK: + // if m_bExtrapolatePrs = true: + // is_marked() = true also for pressure-DoFs inside the particle!! + // -> see: particle_tools.h: if ( m_dExtrapolatePrs ) ... + /////////////////////////////////////////////////////////// + if ( !is_marked(multi_index_row, Index, &prtIndex, &indexList1) ) + { + + for(size_t fct2=0; fct2 < lmat.num_all_col_fct(); ++fct2) + for(size_t dof2=0; dof2 < lmat.num_all_col_dof(fct2); ++dof2) + { + const size_t colIndex = colInd.index(fct2,dof2); + const size_t colComp = colInd.comp(fct2,dof2); + + DoFIndex multi_index_col = DoFIndex(colIndex, colComp); + + // if the target DoF is 'inside the fluid' OR 'pressure-DoF': do usual assembling... + /////////////////////////////////////////////////////////// + // REMARK: + // if m_bExtrapolatePrs = true: + // is_marked() = true also for pressure-DoFs inside the particle!! + // -> see: particle_tools.h: if ( m_dExtrapolatePrs ) ... + /////////////////////////////////////////////////////////// + if ( !is_marked(multi_index_col, Index, &prtIndex, &indexList1) ) + { + DoFRef(mat, multi_index_row, multi_index_col) + += lmat.value(fct1,dof1,fct2,dof2); + } + // if the target DoF is a velocity DoF in the particle: RECONNECT to Trans/Rot + else + { + // CHECK for elements, cut by two different particles: + if ( prtIndex_ref == -1 ) + prtIndex_ref = prtIndex; + + // get indices for re-Association: + DoFIndex transInd = m_myParticle->get_transInd_Comp(Index, prtIndex, fct2); + if ( !m_myParticle->m_bExtrapolate && (int)fct2 != dim ) + { + // CONNECT to Trans: + DoFRef(mat, multi_index_row, transInd) + += lmat.value(fct1,dof1,fct2,dof2); + + //UG_THROW("lmat.value(fct1,dof1,fct2,dof2) =" << lmat.value(fct1,dof1,fct2,dof2) << "\n"); + + // CONNECT to Rot: + if ( 1 ) {//fct1 != dim ){ + MathMatrix rotationMat; + get_rotationMat(multi_index_col, Index, prtIndex, rotationMat); + std::vector rotInd_ = m_myParticle->get_rotInd(Index, prtIndex); + for ( int cmp = 0; cmp < dim; ++cmp ) + DoFRef(mat, multi_index_row, rotInd_[cmp]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMat[fct2][cmp]; + } + } + else if ( (!m_myParticle->m_bExtrapolatePrs && (int)fct2 == dim) ) //( m_myParticle->m_ExtrapolationPrsMethod == 6 && (int)fct2 == dim) || + { + // do usual assembling for pressure DoF inside particle: + DoFRef(mat, multi_index_row, multi_index_col) + += lmat.value(fct1,dof1,fct2,dof2); + } + else if ( m_myParticle->m_bExtrapolatePrs && (int)fct1 == dim && (int)fct2 != dim ) + { + UG_THROW("Haehhh...dieser fall sollte schon abgedeckt sein?...:(...\n"); + if ( (int)fct2 != dim ) + { + // fct2 != dim => die standart coeffs fuer u\cdot n uebernehmen: + // CONNECT to Trans: + DoFRef(mat, multi_index_row, transInd) + += lmat.value(fct1,dof1,fct2,dof2); + + // CONNECT to Rot: + MathMatrix rotationMat; + get_rotationMat(multi_index_col, Index, prtIndex, rotationMat); + std::vector rotInd_ = m_myParticle->get_rotInd(Index, prtIndex); + for ( int cmp = 0; cmp < dim; ++cmp ) + DoFRef(mat, multi_index_row, rotInd_[cmp]) + += lmat.value(fct1,dof1,fct2,dof2)*rotationMat[fct2][cmp]; + } + + } + else //if ( (int) fct1 != dim && (int) fct2 == dim ) // druck beitraege aus ContEq (also fuer stab) werden einfach weggelassen! + { + + ////////////////////////////////////////////////////////////////////////// + // EXTRAPOLATION-AKTION + // + // 'isBorder' and 'coefficients' are computed depending on the + // chosen 'm_ExtrapolationMethod' + ////////////////////////////////////////////////////////////////////////// + // for ( size_t f = 0; f < lmat.num_all_row_dof(0); ++f ) + // UG_LOG("ind(" << f << ") = " << rowInd.index(0,f) << "\n"); + + std::vector ind; + for ( size_t f = 0; f < lmat.num_all_row_dof(0); ++f ) + ind.push_back(rowInd.index(0,f)); + + bool isBorder = false; // -> only substitute velocity-DoFs + vVertexExtrapolData coefficients; + size_t coeffComp; + + ////////////////////////////////////////////////////////////////////////// + // 'isBorder' and 'coefficients' + ////////////////////////////////////////////////////////////////////////// + if ( (int)fct2 != dim ) + { + if ( !m_myParticle->m_bExtrapolate ) + {UG_THROW("Mince!....case wrong handeled!....: IFF extrapolation of VELOCITY is NOT set, this case may not occur!\n");} + + coeffComp = colComp; + isBorder = m_myParticle->m_myExtrapolation->getCoefficients_byDoFIndex(&coefficients, multi_index_col, ind, Index, prtIndex); + } + else + { + if ( !m_myParticle->m_bExtrapolatePrs ) + {UG_THROW("Mince!....case wrong handeled!....: IFF extrapolation of PRESSURE is NOT set, this case may not occur!\n");} + + // re-set 'colComp', since in coefficients[] for pressure-extrapolation + // only 1 connection is stored! + coeffComp = 0; + isBorder = m_myParticle->m_myExtrapolationPrs->getCoefficients_byDoFIndex(&coefficients, multi_index_col, ind, Index, prtIndex); + + } + + ////////////////////////////////////////////////////////////////////////// + // final assembling with coefficient-weighting + // identically for BOTH extrapolationMethods!! + ////////////////////////////////////////////////////////////////////////// + if ( isBorder ) + { + + /// wird fuer Aufruf von 'projectDefect()' in 'particle_constraint_impl.h': + // std::pair indexPair = std::make_pair(multi_index_row, multi_index_col); + + // if ( m_myParticle->m_bExtrapolatePrs && (int)fct2 == dim ) + // m_myParticle->m_myExtrapolationPrs->set_locJData(lmat.value(fct1,dof1,fct2,dof2), indexPair, coefficients, Index, prtIndex); + + if ( multi_index_row[0] == 1783 ){ + UG_LOG("_____________ multi_index_row: " << multi_index_row << "\n"); + + UG_LOG("_____________ coeff.size(): " << coefficients[0].size() << "\n"); + UG_LOG("_____________ lmat.value(): " << lmat.value(fct1,dof1,fct2,dof2) << "\n"); + } + // write new entries coming from extrapolating equation for outVrt: + for ( size_t i = 0; i < coefficients[0].size(); ++i ) + { + + const size_t writeIndex = coefficients[coeffComp][i].second[0]; + const size_t writeComp = coefficients[coeffComp][i].second[1]; + const number lambda = coefficients[coeffComp][i].first; + DoFIndex writeInd = DoFIndex(writeIndex, writeComp); + + + //UG_LOG("ind_row: " << multi_index_row << "Ind_col: " << writeInd << "\n"); + //UG_LOG("lambda: " << lambda << "\n"); + + DoFRef(mat, multi_index_row, writeInd) + += lmat.value(fct1,dof1,fct2,dof2)*lambda; + } + //UG_LOG("_____\n"); + + } // end 'm_myParticle->m_bExtrapolate ' + + + } // else ( m_bExtrapolate = true ) + } + } // end dof2_loop + + + } // end !is_marked() + + + } // end dof1-loop + } // end fct1-loop + +} + +template +void ParticleMapper:: +add_local_vec_to_global_usual(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd) +{ + +// get level index for 'isFluidDoF()' - level dependent! + const int Index = m_myParticle->get_Index(dd->grid_level()); + + const LocalIndices& ind = lvec.get_indices(); + + // index of particle, the element is associated to + int prtIndex, prtIndex_ref = -1; + size_t indexList1 = 1013; + + bool cutElem = false; + if (1 ) // m_myParticle->m_bExtrapolatePrs ) + { +// bool skipAssemblingForOutsideElem; +// cutElem = elemIsCut(ind, lvec.num_all_dof(0), skipAssemblingForOutsideElem, Index, &prtIndex); + cutElem = elemIsCut(ind, lvec.num_all_dof(0), Index, &prtIndex, dd); + + if ( 0 ) //!cutElem ) + if ( skipAssemblingForOutsideElem ) + return; + } + + + + for(size_t fct=0; fct < lvec.num_all_fct(); ++fct) + { + // skip assembling of ContEy on cutElem in order to discretize the pure + // mass flux usind u \dot n via 'add_PureMassFlux' in 'particle_constraint_imol.h' + if ( m_myParticle->m_bExtrapolatePrs ) + if ( m_myParticle->m_myExtrapolationPrs->computePureMassFlux() && cutElem && (int)fct == dim ) + continue; + + for(size_t dof=0; dof < lvec.num_all_dof(fct); ++dof) + { + const size_t VecIndex = ind.index(fct,dof); + const size_t VecComp = ind.comp(fct,dof); + + DoFIndex multi_index = DoFIndex(VecIndex, VecComp); + + // if the corresponding DoF is 'inside the fluid' OR 'pressure-DoF': + if ( !is_marked(multi_index, Index, &prtIndex, &indexList1) ) + { + + // throw error, if defect has value 'nan': + if ( lvec.value(fct,dof) != lvec.value(fct,dof)) + { + UG_LOG("multiindex: " << multi_index << "\t" << indexList1 << "\n"); + UG_THROW("ParticleMap:add_local_vec_to_global: Matrix entry with error: lvec.value(fct,dof) = " << lvec.value(fct,dof) << "\n"); + } + + DoFRef(vec, multi_index) += lvec.value(fct,dof); + + } + else if ( !m_myParticle->m_bDefectByHand ) + { + if ( dim == 3 ) + UG_THROW("in 'add_local_vec_to_global': NOT implemented for 3d!...EXIT!..\n"); + + // CHECK for elements, cut by two different particles: + if ( prtIndex_ref == -1 ) + prtIndex_ref = prtIndex; + + // get ExtraIndices - for WRITING DoFRef(vec,ind): + DoFIndex transInd = m_myParticle->get_transInd_Comp(Index, prtIndex, fct); + DoFIndex rotInd = m_myParticle->get_rotInd_Comp(Index, prtIndex, 0); + + MathVector RotVec; + size_t cmp; + + + // FIRST: get radialVector before adding to global vector + DoFIndex Ind = m_myParticle->m_vvvIndexRadialPair_List[Index][prtIndex][indexList1].first; + MathVector radialVector = m_myParticle->m_vvvIndexRadialPair_List[Index][prtIndex][indexList1].second; + RotVec[0] = -radialVector[1]; + RotVec[1] = radialVector[0]; + cmp = Ind[1]; + + + // SECOND: adding to global vector + // ADD to Trans: + DoFRef(vec, transInd) += lvec.value(fct,dof); + // ADD to Rot: + DoFRef(vec, rotInd) += lvec.value(fct,dof)*RotVec[cmp]; + + } // end else + + + } // end dof-loop + } // end fct-loop + + +} +*/ + +} // end namespace NavierStokes +} // end namespace ug + + + +#endif /* PARTICLE_MAPPER_TOOLS_H_ */ diff --git a/incompressible/fv1/moving_particle/meanID_tools.h b/incompressible/fv1/moving_particle/meanID_tools.h new file mode 100644 index 0000000..ee3376a --- /dev/null +++ b/incompressible/fv1/moving_particle/meanID_tools.h @@ -0,0 +1,1732 @@ +/* + * moving_particle_tools.h + * + * Created on: 20.01.2015 + * Author: suze + */ + +#ifndef MEAN_ID_H_ +#define MEAN_ID_H_ + +namespace ug{ +namespace NavierStokes{ + +/* + + template + number MovingParticle:: + compute_functional_fixed(const size_t n, vector_type& u, SmartPtr > spApproxSpace, + SmartPtr > spMaster, const int topLevel) + { + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + // get data + typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); + + // create Function Group + FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); + + // get subset handler + ConstSmartPtr rSH = dd->subset_handler(); + + // get iterators for all elems on subset + typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; + + typename DoFDistribution::traits::const_iterator iter, iterEnd; + iter = dd->begin(); + iterEnd = dd->end(); + + size_t numDoFs = 0.5 * (n+1) * (n+2); // = 45; 36 :) + + + number D_kVol = 0.0; + number D_kSurf = 0.0; + std::vector gradD(2*numDoFs, 0.0); + + size_t counterFixed = 0; + // loop elements in order to compute 'U_global' and 'omega_global': + for( ; iter != iterEnd; ++iter) + { + // get element + grid_base_object* elem = *iter; + + std::vector vVertex; + CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + + // loop vertices + for (size_t v = 0; v < vVertex.size(); ++v) + { + UG_LOG("vrt_" << v << ": " << aaPos[vVertex[v]][0] << "\t" << aaPos[vVertex[v]][1] << "\n"); + } + + ////////////////////////////////////////////////// + // compute data: + std::vector > vCornerCoords; + CollectCornerCoordinates(vCornerCoords, *elem, aaPos, true); + + number areaTria = ElementSize(ROID_TRIANGLE, &vCornerCoords[0]); + + ////////////////////////////////////////////////// + // loop edges and: + // -> compute 'baseLineSquared', 'baseLine', 'dist' + // -> collect associated vertex 'vrtOut', 'vIndex_Out' + + std::vector vEdges; + CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); + + // values to be computed: + number baseLineSquared, baseLine; + MathVector dist; + size_t vIndex_Out; + Vertex* vrtOut; + + for(size_t e = 0; e < vEdges.size(); ++e) + { + Edge* edge = vEdges[e]; + + if ( rSH->get_subset_index(edge) != 3 ) + { + UG_LOG("...continue...subset = " << rSH->get_subset_index(edge) << "\n"); + continue; + } + + UG_LOG("subset = " << rSH->get_subset_index(edge) << "\n"); + + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); + if ( vVertexEdge.size() != 2 ) + UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); + + Vertex* vrt1 = vVertexEdge[0]; + Vertex* vrt2 = vVertexEdge[1]; + + baseLineSquared = VecDistanceSq(aaPos[vrt1], aaPos[vrt2]); + baseLine = sqrt(baseLineSquared); + dist[0] = fabs(aaPos[vrt1][0] - aaPos[vrt2][0]); + dist[1] = fabs(aaPos[vrt1][1] - aaPos[vrt2][1]); + + // loop vertices and get vrtOut: + for (size_t v = 0; v < vVertex.size(); ++v) + { + if ( (vVertex[v] != vrt1) && (vVertex[v] != vrt2) ) + { + vrtOut = vVertex[v]; + vIndex_Out = v; + } + } + + UG_LOG("vrt1: " << aaPos[vrt1][0] << "\t" << aaPos[vrt1][1] << "\n"); + UG_LOG("vrt2: " << aaPos[vrt2][0] << "\t" << aaPos[vrt2][1] << "\n"); + UG_LOG("vrtOut: " << aaPos[vrtOut][0] << "\t" << aaPos[vrtOut][1] << "\n"); + + } // end edge-loop + UG_LOG("new edge\n"); + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // (1) functional computations: + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////// + // volume computations: + if ( rSH->get_subset_index(elem) == 0 ) + + { + D_kVol += 0.5 * baseLineSquared/areaTria; + } + ////////////////////////////////////////////////// + // surface computations: + else if ( rSH->get_subset_index(elem) == 4 ) + { + D_kSurf += 0.5 * baseLineSquared/areaTria; + } + else { + UG_LOG("elem subset index = " << rSH->get_subset_index(elem) << "\n"); + + UG_THROW("why more than 2 subsets possible?\n"); + } + + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // (2) gradient computations: + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////// + // (1) get global indices of vrt1, vrt2, vrtOut for final adding up to DoF-vector in (4): + + std::vector Ind; + dd->dof_indices(elem, 1, Ind); // #instead-ToDo: dd->dof_indices(elem, cmp, Ind); + + for (size_t v = 0; v < vVertex.size(); ++v) + UG_LOG("2 Ind = " << Ind[v] << "\n"); + + + + //////////////////////////////////////////////////////////////////////////////// + // #instead-ToDo: loop components 'cmp' = x- and y-direction: + for (size_t cmp = 0; cmp < dim; ++cmp) + { + for (size_t v = 0; v < vVertex.size(); ++v) + { + + std::vector vInd; + if(dd->inner_dof_indices(vVertex[v], cmp, vInd) != 1) + UG_THROW("1: error in inner_dof_indices operatio!\n"); + + size_t Index = Ind[v][0]; + + + UG_LOG("Index = " << Index << "\n"); + UG_LOG("vInd_0[0] = " << vInd[0] << "\n"); + + + // boundary nodes are fixed and therefore no DoFs: + if ( rSH->get_subset_index(vVertex[v]) == 1 || rSH->get_subset_index(vVertex[v]) == 2 || rSH->get_subset_index(vVertex[v]) == 3 || rSH->get_subset_index(vVertex[v]) == 5 ) + { + DoFRef(u, vInd[0]) = 0.0; + + ++counterFixed; + continue; + } + + ////////////////////////////////////////////////// + // (2) data to be computed for the gradient computations + number gradD_elem; + number gradA_elem; + + // get indices modulo 2 + size_t index_1 = (v+1)%3; + size_t index_2 = (v+2)%3; + + gradA_elem = fabs(aaPos[vVertex[index_1]][(cmp+1)%2] - aaPos[vVertex[index_2]][(cmp+1)%2]); + + + // ToDo: Vorzeichen für Ableitung von Area A(x1, x2, x3) checken: wirkliche fabs()? + + if ( (vVertex[v] != vrtOut) ) + { + if ( v == vIndex_Out ) UG_THROW("1: error in vIndex_Out computation!\n"); + + gradD_elem = 2*dist[cmp]; + } + else + { + if ( v != vIndex_Out ) UG_THROW("2: error in vIndex_Out computation!\n"); + + gradD_elem = 0.0; + } + + + + ////////////////////////////////////////////////// + // (3) gradient computations: + + + ////////////////////////////////////////////////// + // (3.1) volume computations: + if ( rSH->get_subset_index(elem) == 0 ) + + { + UG_LOG("elem subset index = 0:" << rSH->get_subset_index(elem) << "\n"); + + number gradD_kVol = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); + + ////////////////////////////////////////////////// + // (4) add up all computations to entry of DoF-vector: + // gradD[Index] += gradD_kVol_x/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... + // gradD[numDoFs + Index] += gradD_kVol_y/(n*n); // ToDo! + DoFRef(u, vInd[0]) += (-1.0) * gradD_kVol/(n*n); + } + + ////////////////////////////////////////////////// + // (3.2) surface computations: + else if ( rSH->get_subset_index(elem) == 4 ) + { + UG_LOG("elem subset index = 4:" << rSH->get_subset_index(elem) << "\n"); + + number gradD_kSurf = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); + + ////////////////////////////////////////////////////////// + // (4) add up all computations to entry of DoF-vector: + // gradD[Index] -= gradD_kSurf_x*(n-1)/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... + // gradD[numDoFs + Index] -= gradD_kSurf_y*(n-1)/(n*n); // ToDo! + DoFRef(u, vInd[0]) -= (-1.0) * gradD_kSurf*(n-1)/(n*n); + } + else + { + UG_LOG("elem subset index = " << rSH->get_subset_index(elem) << "\n"); + UG_THROW("--> why more than 2 subsets possible?\n"); + } + + + + UG_LOG("\n ---> v = " << v << " and Ind = " << Ind[v] << "\n"); + + }// end vrt-loop + + }// end cmp-loop + + } // end elem-loop + + number functional = D_kVol/(n*n) - D_kSurf*(n-1)/(n*n); + + UG_LOG("counterFixed = " << counterFixed << "\n"); + + return functional; + + } +*/ +/* + template + number MovingParticle:: + compute_functional_combined(const size_t n, vector_type& u, SmartPtr > spApproxSpace, + SmartPtr > spMaster, const int topLevel) + { + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + // get data + typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); + + // create Function Group + FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); + + // get subset handler + ConstSmartPtr rSH = dd->subset_handler(); + + // get iterators for all elems on subset + typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; + + typename DoFDistribution::traits::const_iterator iter, iterEnd; + iter = dd->begin(); + iterEnd = dd->end(); + + size_t numDoFs = 0.5 * (n+1) * (n+2); // = 45; 36 :) + + + number D_kVol = 0.0; + number D_kSurf = 0.0; + std::vector gradD(2*numDoFs, 0.0); + + // loop elements in order to compute 'U_global' and 'omega_global': + for( ; iter != iterEnd; ++iter) + { + // get element + grid_base_object* elem = *iter; + + std::vector vVertex; + CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + + // loop vertices + for (size_t v = 0; v < vVertex.size(); ++v) + { + UG_LOG("vrt_" << v << ": " << aaPos[vVertex[v]][0] << "\t" << aaPos[vVertex[v]][1] << "\n"); + } + + ////////////////////////////////////////////////// + // compute data: + std::vector > vCornerCoords; + CollectCornerCoordinates(vCornerCoords, *elem, aaPos, true); + + number areaTria = ElementSize(ROID_TRIANGLE, &vCornerCoords[0]); + + ////////////////////////////////////////////////// + // loop edges and: + // -> compute 'baseLineSquared', 'baseLine', 'dist' + // -> collect associated vertex 'vrtOut', 'vIndex_Out' + + std::vector vEdges; + CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); + + // values to be computed: + number baseLineSquared, baseLine; + MathVector dist; + size_t vIndex_Out; + Vertex* vrtOut; + + for(size_t e = 0; e < vEdges.size(); ++e) + { + Edge* edge = vEdges[e]; + + if ( rSH->get_subset_index(edge) != 3 ) + { + UG_LOG("...continue...subset = " << rSH->get_subset_index(edge) << "\n"); + continue; + } + + UG_LOG("subset = " << rSH->get_subset_index(edge) << "\n"); + + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); + if ( vVertexEdge.size() != 2 ) + UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); + + Vertex* vrt1 = vVertexEdge[0]; + Vertex* vrt2 = vVertexEdge[1]; + + baseLineSquared = VecDistanceSq(aaPos[vrt1], aaPos[vrt2]); + baseLine = sqrt(baseLineSquared); + dist[0] = fabs(aaPos[vrt1][0] - aaPos[vrt2][0]); + dist[1] = fabs(aaPos[vrt1][1] - aaPos[vrt2][1]); + + // loop vertices and get vrtOut: + for (size_t v = 0; v < vVertex.size(); ++v) + { + if ( (vVertex[v] != vrt1) && (vVertex[v] != vrt2) ) + { + vrtOut = vVertex[v]; + vIndex_Out = v; + } + } + + UG_LOG("vrt1: " << aaPos[vrt1][0] << "\t" << aaPos[vrt1][1] << "\n"); + UG_LOG("vrt2: " << aaPos[vrt2][0] << "\t" << aaPos[vrt2][1] << "\n"); + UG_LOG("vrtOut: " << aaPos[vrtOut][0] << "\t" << aaPos[vrtOut][1] << "\n"); + + } // end edge-loop + UG_LOG("new edge\n"); + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // (1) functional computations: + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////// + // volume computations: + if ( rSH->get_subset_index(elem) == 0 ) + + { + D_kVol += 0.5 * baseLineSquared/areaTria; + } + ////////////////////////////////////////////////// + // surface computations: + else if ( rSH->get_subset_index(elem) == 4 ) + { + D_kSurf += 0.5 * baseLineSquared/areaTria; + } + else { + UG_LOG("elem subset index = " << rSH->get_subset_index(elem) << "\n"); + + UG_THROW("why more than 2 subsets possible?\n"); + } + + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // (2) gradient computations: + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////// + // (1) get global indices of vrt1, vrt2, vrtOut for final adding up to DoF-vector in (4): + + std::vector Ind; + dd->dof_indices(elem, 1, Ind); // #instead-ToDo: dd->dof_indices(elem, cmp, Ind); + + for (size_t v = 0; v < vVertex.size(); ++v) + UG_LOG("2 Ind = " << Ind[v] << "\n"); + + + number _A_ = (aaPos[vVertex[1]][1]-aaPos[vVertex[0]][1])*(aaPos[vVertex[2]][0]-aaPos[vVertex[0]][0]) + -(aaPos[vVertex[1]][0]-aaPos[vVertex[0]][0])*(aaPos[vVertex[2]][1]-aaPos[vVertex[0]][1]); + + number gradA_scale = 0.5 * _A_ / fabs(_A_); + + // if ( gradA_scale > 0 ) + // UG_LOG("gradA_scale = " << gradA_scale << "\n"); + + //////////////////////////////////////////////////////////////////////////////// + // #instead-ToDo: loop components 'cmp' = x- and y-direction: + for (size_t cmp = 0; cmp < dim; ++cmp) + { + for (size_t v = 0; v < vVertex.size(); ++v) + { + std::vector vInd; + if(dd->inner_dof_indices(vVertex[v], cmp, vInd) != 1) + UG_THROW("1: error in inner_dof_indices operatio!\n"); + + size_t Index = Ind[v][0]; + + + UG_LOG("Index = " << Index << "\n"); + UG_LOG("vInd_0[0] = " << vInd[0] << "\n"); + + ////////////////////////////////////////////////// + // (2) data to be computed for the gradient computations + number gradD_elem; + number gradA_elem; + + // get indices modulo 2 + size_t ind_1 = (v+1)%3; + size_t ind_2 = (v+2)%3; + size_t cmp_shift = (cmp+1)%2; + + UG_LOG("-------> cmp_shift = " << cmp_shift << "\n"); + + + if ( cmp_shift == 0 ) // ind_2 - ind_1 + gradA_elem = 0.5 * aaPos[vVertex[ind_2]][cmp_shift] - aaPos[vVertex[ind_1]][cmp_shift]; + else if ( cmp_shift == 1 ) // ind_1 - ind_2 + gradA_elem = 0.5 * aaPos[vVertex[ind_1]][cmp_shift] - aaPos[vVertex[ind_2]][cmp_shift]; + else UG_THROW("cmp_shift not valid: " << cmp_shift << "\n"); + + //gradA_elem = 0.5 * aaPos[vVertex[ind_1]][(cmp+1)%2] - aaPos[vVertex[ind_2]][(cmp+1)%2]); + UG_LOG("-------> gradA_elem = " << gradA_elem << "\n"); + + //gradA_elem *= gradA_scale; + + + // ToDo: Vorzeichen für Ableitung von Area A(x1, x2, x3) checken: wirkliche fabs()? + + if ( (vVertex[v] != vrtOut) ) + { + if ( v == vIndex_Out ) UG_THROW("1: error in vIndex_Out computation!\n"); + + gradD_elem = 2*dist[cmp]; + } + else + { + if ( v != vIndex_Out ) UG_THROW("2: error in vIndex_Out computation!\n"); + + gradD_elem = 0.0; + } + + + + ////////////////////////////////////////////////// + // (3) gradient computations: + + + ////////////////////////////////////////////////// + // (3.1) volume computations: + if ( rSH->get_subset_index(elem) == 0 ) + + { + UG_LOG("elem subset index = 0:" << rSH->get_subset_index(elem) << "\n"); + + number gradD_kVol = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); + + ////////////////////////////////////////////////// + // (4) add up all computations to entry of DoF-vector: + // gradD[Index] += gradD_kVol_x/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... + // gradD[numDoFs + Index] += gradD_kVol_y/(n*n); // ToDo! + DoFRef(u, vInd[0]) += (-1.0) * gradD_kVol/(n*n); + if ( vInd[0][0] == 18 && cmp == 0 ) + { + UG_LOG("gradD_elem = " << gradD_elem << "\n"); + UG_LOG("gradA_elem = " << gradA_elem << "\n"); + UG_LOG("gradA_scale = " << gradA_scale << "\n"); + UG_LOG("areaTria = " << areaTria << "\n"); + UG_LOG("baseLineSquared = " << baseLineSquared << "\n"); + + UG_LOG("gradD_kVol = " << gradD_kVol << "\n"); + UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); + } + } + + ////////////////////////////////////////////////// + // (3.2) surface computations: + else if ( rSH->get_subset_index(elem) == 4 ) + { + UG_LOG("elem subset index = 4:" << rSH->get_subset_index(elem) << "\n"); + + number gradD_kSurf = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); + + ////////////////////////////////////////////////////////// + // (4) add up all computations to entry of DoF-vector: + // gradD[Index] -= gradD_kSurf_x*(n-1)/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... + // gradD[numDoFs + Index] -= gradD_kSurf_y*(n-1)/(n*n); // ToDo! + DoFRef(u, vInd[0]) -= (-1.0) * gradD_kSurf*(n-1)/(n*n); + if ( vInd[0][0] == 18 && cmp == 0 ) + { + UG_LOG("gradD_elem = " << gradD_elem << "\n"); + UG_LOG("gradA_elem = " << gradA_elem << "\n"); + UG_LOG("gradA_scale = " << gradA_scale << "\n"); + UG_LOG("areaTria = " << areaTria << "\n"); + UG_LOG("baseLineSquared = " << baseLineSquared << "\n"); + + UG_LOG("gradD_kSurf = " << gradD_kSurf << "\n"); + UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); + } + } + else + { + UG_LOG("elem subset index = " << rSH->get_subset_index(elem) << "\n"); + UG_THROW("--> why more than 2 subsets possible?\n"); + } + + + + UG_LOG("\n ---> v = " << v << " and Ind = " << Ind[v] << "\n"); + + }// end vrt-loop + + }// end cmp-loop + + } // end elem-loop + + number functional = D_kVol/(n*n) - D_kSurf*(n-1)/(n*n); + functional *= functional; + + return functional; + + } + */ + +template +number MovingParticle:: +compute_functional_all(const size_t n, vector_type& u, SmartPtr > spApproxSpace, + SmartPtr > spMaster, const int topLevel) +{ + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + // get data + typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); + + // create Function Group + FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); + + // get subset handler + ConstSmartPtr rSH = dd->subset_handler(); + + // get iterators for all elems on subset + typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; + + typename DoFDistribution::traits::const_iterator iter, iterEnd; + iter = dd->begin(); + iterEnd = dd->end(); + + size_t numDoFs = 0.5 * (n+1) * (n+2); // = 45; 36 :) + + number D_kVol = 0.0; + number D_kSurf = 0.0; + std::vector gradD(2*numDoFs, 0.0); + + int counter1, counter2, counter3, counter0, counter5; + counter1 = counter2 = counter3 = counter5 = counter0 = 0; + + + // loop elements in order to compute 'U_global' and 'omega_global': + for( ; iter != iterEnd; ++iter) + { + counter0 += 1; + // get element + grid_base_object* elem = *iter; + + std::vector vVertex; + CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + for (size_t v = 0; v < vVertex.size(); ++v) + UG_LOG("vrt_" << v << ": " << aaPos[vVertex[v]][0] << "\t" << aaPos[vVertex[v]][1] << "\n"); + + + ////////////////////////////////////////////////// + // compute data: + std::vector > vCornerCoords; + CollectCornerCoordinates(vCornerCoords, *elem, aaPos, true); + + number areaTria = ElementSize(ROID_TRIANGLE, &vCornerCoords[0]); + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // (1) functional computations: + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////// + // volume computations ---> ALWAYS!! + + std::vector vEdges; + CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); + + // loop edges + for(size_t e = 0; e < vEdges.size(); ++e) + { + Edge* edge = vEdges[e]; + + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); + if ( vVertexEdge.size() != 2 ) + UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); + + number baseLineSquared = VecDistanceSq(aaPos[vVertexEdge[0]], aaPos[vVertexEdge[1]]); + + D_kVol += baseLineSquared/(2*areaTria); + + } + + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // surface computations - again: + + //////////////////////////////////////////////////////////////////////////////// + // FIRST: get subSet of boundary element (exclude inner elements (0) ) + int subSet = rSH->get_subset_index(elem); + + //////////////////////////////////////////////////////////////////////////////// + // data filled for subSet = 1,2,3 and 5 + // AND needed for later computations! + size_t indexA, indexB, indexC; + std::vector vEdgesS(3); + std::vector vBaseLine(3); + number sSq = 0.0; + number sSq_all = 0.0; + + std::vector vEdges_buffer; + CollectEdgesSorted(vEdges_buffer, *m_spParticleHandlerGlobal->m_spMG, elem); + + if ( subSet == 5 ) + { + counter5 += 1; + // collect all vertices of the element + std::vector vVertexS_buffer; + std::vector vVertexS(3); + CollectVertices(vVertexS_buffer, *m_spParticleHandlerGlobal->m_spMG, elem); + + // loop all vertices; treat them as vertex A as in the case below; add up and weight with 1/3: + for(size_t countA = 0; countA < 3; ++countA) + { + // now store the other indices in order: + indexA = countA; + indexC = (countA+1)%3; + indexB = (countA+2)%3; + + //////////////////////////////////////////////////////////////////////////////// + // (1) collect 'vVertexS': + vVertexS[0] = vVertexS_buffer[indexA]; + vVertexS[1] = vVertexS_buffer[indexC]; + vVertexS[2] = vVertexS_buffer[indexB]; + + UG_LOG("---------> vVertexS: " << aaPos[vVertexS[0]][0] << "\t" << aaPos[vVertexS[0]][1] << "\n"); + UG_LOG("---------> vVertexS: " << aaPos[vVertexS[1]][0] << "\t" << aaPos[vVertexS[1]][1] << "\n"); + UG_LOG("---------> vVertexS: " << aaPos[vVertexS[2]][0] << "\t" << aaPos[vVertexS[2]][1] << "\n"); + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // (B) loop edges ---> for boundary elements with subset 'subSet': + + // loop edges + for(size_t e = 0; e < vEdges_buffer.size(); ++e) + { + Edge* edge = vEdges_buffer[e]; + + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); + if ( vVertexEdge.size() != 2 ) + UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); + + // choose the edge, which does NOT contain the vertex A: + if ( (vVertexEdge[0] != vVertexS[0]) && (vVertexEdge[1] != vVertexS[0]) ) + { + vEdgesS[0] = edge; + indexA = e; + break; + } + } + // now store the other indices in order: + indexB = (indexA+1)%3; + indexC = (indexA+2)%3; + + //ToDo: egal, was indexB und indexC ist, solange NICHT indexA = subSet?? + + //////////////////////////////////////////////////////////////////////////////// + // (2) collect 'vEdgesS': + vEdgesS[1] = vEdges_buffer[indexB]; + vEdgesS[2] = vEdges_buffer[indexC]; + + //////////////////////////////////////////////////////////////////////////////// + // (3) collect 'vBaseLine': + for(size_t i = 0; i < 3; ++i) + { + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, vEdgesS[i]); + if ( vVertexEdge.size() != 2 ) + UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); + + UG_LOG("---------> vVertexEdge1: " << aaPos[vVertexEdge[0]][0] << "\t" << aaPos[vVertexEdge[0]][1] << "\n"); + UG_LOG("---------> vVertexEdge2: " << aaPos[vVertexEdge[1]][0] << "\t" << aaPos[vVertexEdge[1]][1] << "\n"); + + number baseLineSquared = VecDistanceSq(aaPos[vVertexEdge[0]], aaPos[vVertexEdge[1]]); + vBaseLine[i] = sqrt(baseLineSquared); + } + + //////////////////////////////////////////////////////////////////////////////// + // THIRD: compute data for surface integrals ---> s, alphaB, alphaC + + number a = vBaseLine[0]; + number b = vBaseLine[1]; + number c = vBaseLine[2]; + number aSq = a*a; + number bSq = b*b; + number cSq = c*c; + + number s = 0.5*sqrt(2 * (bSq+cSq) - aSq); + sSq = s*s; + sSq_all += sSq; + UG_LOG("---------> sSq: " << sSq << "\n"); + UG_LOG("---------> sSq_all: " << sSq_all << "\n"); + + number cosAlphaB = (bSq + sSq - 0.25*aSq)/(2*b*s); + number cosAlphaC = (cSq + sSq - 0.25*aSq)/(2*c*s); + + //////////////////////////////////////////////////////////////////////////////// + // FINALLY: compute fluxes + + number fluxB = 0.5*s*b*cosAlphaB/areaTria ; + number fluxC = 0.5*s*c*cosAlphaC/areaTria ; + + D_kSurf += (fluxB + fluxC)/3.0; + + number added = (fluxB + fluxC)/3.0;; + UG_LOG("subSet = " << subSet << "added = " << added << "\n"); + + } // end indexA-loop + } // end case subSet == 5 + + + //////////////////////////////////////////////////////////////////////////////// + // SECOND: loop vertices AND edges --> write data according to specified indices 'indexA, indexB, indexC': + + if ( subSet == 1 ) counter1 += 1; + if ( subSet == 2 ) counter2 += 1; + if ( subSet == 3 ) counter3 += 1; + + //////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // loop edges ---> for boundary elements with subset 'subSet': + + //////////////////////////////////////////////////////////////////////////////// + // THIRD: compute data for surface integrals ---> s, alphaB, alphaC + + if ( subSet == 1 || subSet == 2 || subSet == 3 ) + { + + // loop edges + for(size_t e = 0; e < vEdges_buffer.size(); ++e) + { + if ( rSH->get_subset_index(vEdges_buffer[e]) == subSet ) + { + vEdgesS[0] = vEdges_buffer[e]; + indexA = e; + break; + } + } + // now store the other indices in order: + indexB = (indexA+1)%3; + indexC = (indexA+2)%3; + + //ToDo: egal, was indexB und indexC ist, solange NICHT indexA = subSet?? + + //////////////////////////////////////////////////////////////////////////////// + // (2) collect 'vEdgesS': + vEdgesS[1] = vEdges_buffer[indexB]; + vEdgesS[2] = vEdges_buffer[indexC]; + + //////////////////////////////////////////////////////////////////////////////// + // (3) collect 'vBaseLine': + for(size_t i = 0; i < 3; ++i) + { + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, vEdgesS[i]); + if ( vVertexEdge.size() != 2 ) + UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); + + UG_LOG("---------> vVertexEdge1: " << aaPos[vVertexEdge[0]][0] << "\t" << aaPos[vVertexEdge[0]][1] << "\n"); + UG_LOG("---------> vVertexEdge2: " << aaPos[vVertexEdge[1]][0] << "\t" << aaPos[vVertexEdge[1]][1] << "\n"); + + number BaseLineSquared = VecDistanceSq(aaPos[vVertexEdge[0]], aaPos[vVertexEdge[1]]); + vBaseLine[i] = sqrt(BaseLineSquared); + + } + + number a = vBaseLine[0]; + number b = vBaseLine[1]; + number c = vBaseLine[2]; + number aSq = a*a; + number bSq = b*b; + number cSq = c*c; + + number s = 0.5*sqrt(2 * (bSq+cSq) - aSq); + sSq = s*s; + number cosAlphaB = (bSq + sSq - 0.25*aSq)/(2*b*s); + number cosAlphaC = (cSq + sSq - 0.25*aSq)/(2*c*s); + + //////////////////////////////////////////////////////////////////////////////// + // FINALLY: compute fluxes + + number fluxB_ = 0.5*s*b*cosAlphaB/areaTria ; + number fluxC_ = 0.5*s*c*cosAlphaC/areaTria ; + + number fluxB = 0.5*0.25*(3*bSq + cSq - aSq)/areaTria ; + number fluxC = 0.5*0.25*(3*cSq + bSq - aSq)/areaTria ; + + if ( fabs(fluxB - fluxB_) > 0.00001 ) + UG_THROW(" fluxB: " << fluxB << " and " << " fluxB_: " << fluxB_ << "\n"); + if ( fabs(fluxC - fluxC_) > 0.00001 ) + UG_THROW(" fluxC: " << fluxC << " and " << " fluxC_: " << fluxC_ << "\n"); + + D_kSurf += fluxB + fluxC; + number added = fluxB + fluxC; + UG_LOG("subSet = " << subSet << "added = " << added << "\n"); + + + } // END: functional computations + + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // compute gradients + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////////////// + // compute scaling for gradA_elem: + + number _A_ =(aaPos[vVertex[1]][0]-aaPos[vVertex[0]][0])*(aaPos[vVertex[2]][1]-aaPos[vVertex[0]][1]) + -(aaPos[vVertex[2]][0]-aaPos[vVertex[0]][0])*(aaPos[vVertex[1]][1]-aaPos[vVertex[0]][1]); + + number gradA_scale = _A_ / fabs(_A_); + + //////////////////////////////////////////////////////////////////////////////// + // loop cmp and vertices to compute 'gradS_elem' and + // ADD 'gradA_elem'/'gradA_elem' to gradient: + + number gradA_elem; + number gradD_elem_all; + number gradS_elem; + std::vector vVertexEdge; + + for (size_t cmp = 0; cmp < dim; ++cmp) + { + + for (size_t v = 0; v < vVertex.size(); ++v) + { + std::vector vInd; + if(dd->inner_dof_indices(vVertex[v], cmp, vInd) != 1) + UG_THROW("1: error in inner_dof_indices operatio!\n"); + + UG_LOG("vInd[0] = " << vInd[0] << "\n"); + + //////////////////////////////////////////////////////////////////////////////// + // initialize gradient for the denominator and add all the contributions from the edges + gradS_elem = 0.0; + gradD_elem_all = 0.0; + + //////////////////////////////////////////////////////////////////////////////// + // compute 'gradA_elem': + + // get indices modulo 2 + size_t ind_1 = (v+1)%3; + size_t ind_2 = (v+2)%3; + size_t cmp_shift = (cmp+1)%2; + + // ind_2 - ind_1 + if ( cmp_shift == 0 ) + gradA_elem = 0.5 * (aaPos[vVertex[ind_2]][cmp_shift] - aaPos[vVertex[ind_1]][cmp_shift]); + // ind_1 - ind_2 + else if ( cmp_shift == 1 ) + gradA_elem = 0.5 * (aaPos[vVertex[ind_1]][cmp_shift] - aaPos[vVertex[ind_2]][cmp_shift]); + else + UG_THROW("cmp_shift not valid: " << cmp_shift << "\n"); + + gradA_elem *= gradA_scale; + + + //////////////////////////////////////////////////////////////////////////////// + // compute 'gradS_elem' and 'gradD_elem_all': + + ////////////////////////////////////////////////// + // edge contributions: + + number gradS_elem_scale = 1.0; + std::vector vBaseLineSquared(3); + + if ( subSet == 5 ) + { UG_LOG("---> elem subset index = :" << rSH->get_subset_index(elem) << "\n");} + + for(size_t e = 0; e < 3; ++e) + { + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, vEdges_buffer[e]); + if ( vVertexEdge.size() != 2 ) + UG_THROW("---> error in collecting vertices associated to an edge!....EXIT!...\n"); + + vBaseLineSquared[e] = VecDistanceSq(aaPos[vVertexEdge[0]], aaPos[vVertexEdge[1]]); + + UG_LOG("for 'gradS_elem_scale': vVertexEdge1: " << aaPos[vVertexEdge[0]][0] << "\t" << aaPos[vVertexEdge[0]][1] << "\n"); + UG_LOG("for 'gradS_elem_scale': vVertexEdge2: " << aaPos[vVertexEdge[1]][0] << "\t" << aaPos[vVertexEdge[1]][1] << "\n"); + + + // adapt scale factor for edge = baseLine: + if ( rSH->get_subset_index(vEdges_buffer[e]) == 5 ) + UG_THROW("---> hmmmm: EDGE subset index can NOT be 5! ---> index = :" << rSH->get_subset_index(vEdges_buffer[e]) << "\n"); + + if ( rSH->get_subset_index(vEdges_buffer[e]) == subSet ) + gradS_elem_scale = -0.5; + if ( subSet == 5 ) + gradS_elem_scale = 1.5; + + if ( vVertex[v] == vVertexEdge[0] ) + { + gradS_elem += gradS_elem_scale * 2.0 * (aaPos[vVertexEdge[0]][cmp] - aaPos[vVertexEdge[1]][cmp]); + gradD_elem_all += 2.0 * (aaPos[vVertexEdge[0]][cmp] - aaPos[vVertexEdge[1]][cmp]); + } + else if ( vVertex[v] == vVertexEdge[1] ) + { + gradS_elem += gradS_elem_scale * 2.0 * (aaPos[vVertexEdge[1]][cmp] - aaPos[vVertexEdge[0]][cmp]); + gradD_elem_all += 2.0 * (aaPos[vVertexEdge[0]][cmp] - aaPos[vVertexEdge[1]][cmp]); + } + // else: add 0.0 ==> do nothing... + + } // end edge-loop + + number vBaseLineSquared_all = vBaseLineSquared[0] + vBaseLineSquared[1] + vBaseLineSquared[2]; + + + //////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// + // ADD up all v-th derivatives to 'cmp' of vector 'u': + + ////////////////////////////////////////////////// + // (3.1) volume computations: + + number gradD_kVol = (areaTria*gradD_elem_all - vBaseLineSquared_all*gradA_elem)/(2*areaTria*areaTria); + + DoFRef(u, vInd[0]) += (-1.0) * gradD_kVol/(n*n); + + if (vInd[0][0] == 18 ) + UG_LOG("18: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); + + if (vInd[0][0] == 19 ) + UG_LOG("19: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); + + if (vInd[0][0] == 20 ) + UG_LOG("20: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); + + + if (vInd[0][0] == 21 ) + UG_LOG("21: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); + + + if (vInd[0][0] == 24 ) + UG_LOG("24: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); + + if (vInd[0][0] == 16 ) + UG_LOG("16: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); + + + if ( vInd[0][0] == 18 && cmp == 0 ) + { + UG_LOG("gradD_elem_all = " << gradD_elem_all << "\n"); + UG_LOG("gradA_elem = " << gradA_elem << "\n"); + UG_LOG("gradA_scale = " << gradA_scale << "\n"); + UG_LOG("areaTria = " << areaTria << "\n"); + UG_LOG("vBaseLineSquared_all = " << vBaseLineSquared_all << "\n"); + + UG_LOG("gradD_kVol = " << gradD_kVol << "\n"); + UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); + } + + ////////////////////////////////////////////////// + // (3.2) surface computations: + if ( 0 ) //rSH->get_subset_index(elem) != 0 ) + { + if ( subSet != 1 && subSet != 2 && subSet != 3 ) + { + if ( subSet == 5 ) + { + sSq = sSq_all/3.0; + gradS_elem = gradS_elem/3.0; + UG_LOG("elem subset index = :" << rSH->get_subset_index(elem) << "\n"); + } + else + { UG_THROW("elem subset index = :" << rSH->get_subset_index(elem) << "\n");} + } + + number gradS_kSurf = 0.5 * (areaTria*gradS_elem - sSq*gradA_elem)/(areaTria*areaTria); + + DoFRef(u, vInd[0]) -= (-1.0) * gradS_kSurf/n; + if ( vInd[0][0] == 18 && cmp == 0 ) + { + UG_LOG("gradS_elem = " << gradS_elem << "\n"); + UG_LOG("gradA_elem = " << gradA_elem << "\n"); + UG_LOG("gradA_scale = " << gradA_scale << "\n"); + UG_LOG("areaTria = " << areaTria << "\n"); + + UG_LOG("gradS_kSurf = " << gradS_kSurf << "\n"); + UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); + } + } + + + }// end vrt-loop + + }// end cmp-loop + + } // end elem-loop + + number functional = 0.5 * D_kVol/(n*n) - D_kSurf/n; + functional *= functional; + + UG_LOG(" counter0: " << counter0 << "\n"); + UG_LOG(" counter1: " << counter1 << "\n"); + UG_LOG(" counter2: " << counter2 << "\n"); + UG_LOG(" counter3: " << counter3 << "\n"); + UG_LOG(" counter5: " << counter5 << "\n"); + + + return functional; + +} + + +template +number MovingParticle:: +compute_functional(const size_t n, vector_type& u, SmartPtr > spApproxSpace, + SmartPtr > spMaster, const int topLevel) +{ + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + // get data + typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); + + // create Function Group + FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); + + // get subset handler + ConstSmartPtr rSH = dd->subset_handler(); + + // get iterators for all elems on subset + typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; + + typename DoFDistribution::traits::const_iterator iter, iterEnd; + iter = dd->begin(); + iterEnd = dd->end(); + + size_t numDoFs = 0.5 * (n+1) * (n+2); // = 45; 36 :) + + + number D_kVol = 0.0; + number D_kSurf = 0.0; + std::vector gradD(2*numDoFs, 0.0); + + // loop elements in order to compute 'U_global' and 'omega_global': + for( ; iter != iterEnd; ++iter) + { + // get element + grid_base_object* elem = *iter; + + std::vector vVertex; + CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + + // loop vertices + for (size_t v = 0; v < vVertex.size(); ++v) + { + UG_LOG("vrt_" << v << ": " << aaPos[vVertex[v]][0] << "\t" << aaPos[vVertex[v]][1] << "\n"); + } + + ////////////////////////////////////////////////// + // compute data: + std::vector > vCornerCoords; + CollectCornerCoordinates(vCornerCoords, *elem, aaPos, true); + + number areaTria = ElementSize(ROID_TRIANGLE, &vCornerCoords[0]); + + ////////////////////////////////////////////////// + // loop edges and: + // -> compute 'baseLineSquared', 'baseLine', 'dist' + // -> collect associated vertex 'vrtOut', 'vIndex_Out' + + std::vector vEdges; + CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); + + // values to be computed: + number baseLineSquared, baseLine; + MathVector dist; + size_t vIndex_Out, vIndex_1, vIndex_2; + Vertex* vrtOut; + Vertex* vrt1; + Vertex* vrt2; + + for(size_t e = 0; e < vEdges.size(); ++e) + { + Edge* edge = vEdges[e]; + + if ( rSH->get_subset_index(edge) != 3 ) + { + UG_LOG("...continue...subset = " << rSH->get_subset_index(edge) << "\n"); + continue; + } + + UG_LOG("subset = " << rSH->get_subset_index(edge) << "\n"); + + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); + if ( vVertexEdge.size() != 2 ) + UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); + + vrt1 = vVertexEdge[0]; + vrt2 = vVertexEdge[1]; + + baseLineSquared = VecDistanceSq(aaPos[vrt1], aaPos[vrt2]); + baseLine = sqrt(baseLineSquared); + dist[0] = fabs(aaPos[vrt1][0] - aaPos[vrt2][0]); + dist[1] = fabs(aaPos[vrt1][1] - aaPos[vrt2][1]); + + // loop vertices and get vrtOut: + for (size_t v = 0; v < vVertex.size(); ++v) + { + if ( (vVertex[v] != vrt1) && (vVertex[v] != vrt2) ) + { + vrtOut = vVertex[v]; + vIndex_Out = v; + } + if ( vVertex[v] == vrt1 ) + vIndex_1 = v; + if ( vVertex[v] == vrt2 ) + vIndex_2 = v; + } + + UG_LOG("vrt1: " << aaPos[vrt1][0] << "\t" << aaPos[vrt1][1] << "\n"); + UG_LOG("vrt2: " << aaPos[vrt2][0] << "\t" << aaPos[vrt2][1] << "\n"); + UG_LOG("vrtOut: " << aaPos[vrtOut][0] << "\t" << aaPos[vrtOut][1] << "\n"); + + } // end edge-loop + UG_LOG("new edge\n"); + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // (1) functional computations: + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////// + // volume computations ---> ALWAYS!! + if ( 1 ) //rSH->get_subset_index(elem) == 0 ) + + { + // Attention: the factor 1/2 is removed from D_kVol AND D_kSurf, since it arises in both summands! + D_kVol += baseLineSquared/(2.0*areaTria); + } + ////////////////////////////////////////////////// + // surface computations: + if ( rSH->get_subset_index(elem) == 4 ) + { + // Attention: the factor 1/2 is removed from D_kVol AND D_kSurf, since it arises in both summands! + D_kSurf += baseLineSquared/(2.0*areaTria); + } + + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + // (2) gradient computations: + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////// + // (1) get global indices of vrt1, vrt2, vrtOut for final adding up to DoF-vector in (4): + + std::vector Ind; + dd->dof_indices(elem, 1, Ind); // #instead-ToDo: dd->dof_indices(elem, cmp, Ind); + + for (size_t v = 0; v < vVertex.size(); ++v) + UG_LOG("2 Ind = " << Ind[v] << "\n"); + /* + template <> + inline number ElementSize(const MathVector<2>* vCornerCoords) + { + return(0.5*fabs((vCornerCoords[1][1]-vCornerCoords[0][1])*(vCornerCoords[2][0]-vCornerCoords[0][0]) + -(vCornerCoords[1][0]-vCornerCoords[0][0])*(vCornerCoords[2][1]-vCornerCoords[0][1]))); + } + */ + + number _A_ =(aaPos[vVertex[1]][0]-aaPos[vVertex[0]][0])*(aaPos[vVertex[2]][1]-aaPos[vVertex[0]][1]) + -(aaPos[vVertex[2]][0]-aaPos[vVertex[0]][0])*(aaPos[vVertex[1]][1]-aaPos[vVertex[0]][1]); + + number gradA_scale = _A_ / fabs(_A_); + + // if ( gradA_scale > 0 ) + // UG_LOG("gradA_scale = " << gradA_scale << "\n"); + + //////////////////////////////////////////////////////////////////////////////// + // #instead-ToDo: loop components 'cmp' = x- and y-direction: + for (size_t cmp = 0; cmp < dim; ++cmp) + { + for (size_t v = 0; v < vVertex.size(); ++v) + { + std::vector vInd; + if(dd->inner_dof_indices(vVertex[v], cmp, vInd) != 1) + UG_THROW("1: error in inner_dof_indices operatio!\n"); + + size_t Index = Ind[v][0]; + + + UG_LOG("Index = " << Index << "\n"); + UG_LOG("vInd_0[0] = " << vInd[0] << "\n"); + + ////////////////////////////////////////////////// + // (2) data to be computed for the gradient computations + number gradD_elem; + number gradA_elem; + + // get indices modulo 2 + size_t ind_1 = (v+1)%3; + size_t ind_2 = (v+2)%3; + size_t cmp_shift = (cmp+1)%2; + + UG_LOG("-------> cmp_shift = " << cmp_shift << "\n"); + + + if ( cmp_shift == 0 ) // ind_2 - ind_1 + gradA_elem = 0.5 * (aaPos[vVertex[ind_2]][cmp_shift] - aaPos[vVertex[ind_1]][cmp_shift]); + else if ( cmp_shift == 1 ) // ind_1 - ind_2 + gradA_elem = 0.5 * (aaPos[vVertex[ind_1]][cmp_shift] - aaPos[vVertex[ind_2]][cmp_shift]); + else UG_THROW("cmp_shift not valid: " << cmp_shift << "\n"); + + gradA_elem *= gradA_scale; + + + // ToDo: Vorzeichen für Ableitung von Area A(x1, x2, x3) checken: wirkliche fabs()? + + if ( vVertex[v] != vrtOut ) + { + if ( v == vIndex_Out ) UG_THROW("1: error in vIndex_Out computation!\n"); + + gradD_elem = 2.0 * (aaPos[vrt1][cmp] - aaPos[vrt2][cmp]); + + if ( vVertex[v] == vrt2 ) + { + gradD_elem *= -1.0; + UG_LOG("ind_1: " << ind_1 << "\n"); + UG_LOG("vIndex_1: " << vIndex_1 << "\n"); + UG_LOG("ind_2: " << ind_2 << "\n"); + UG_LOG("vIndex_2: " << vIndex_2 << "\n"); + } + + } + else + { + if ( v != vIndex_Out ) UG_THROW("2: error in vIndex_Out computation!\n"); + + gradD_elem = 0.0; + } + + + + ////////////////////////////////////////////////// + // (3) gradient computations: + + + ////////////////////////////////////////////////// + // (3.1) volume computations: + if ( 1 ) //rSH->get_subset_index(elem) == 0 ) + + { + UG_LOG("elem subset index = 0:" << rSH->get_subset_index(elem) << "\n"); + + number gradD_kVol = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); + + ////////////////////////////////////////////////// + // (4) add up all computations to entry of DoF-vector: + // gradD[Index] += gradD_kVol_x/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... + // gradD[numDoFs + Index] += gradD_kVol_y/(n*n); // ToDo! + DoFRef(u, vInd[0]) += (-1.0) * gradD_kVol/(n*n); + if ( vInd[0][0] == 18 && cmp == 0 ) + { + UG_LOG("gradD_elem = " << gradD_elem << "\n"); + UG_LOG("gradA_elem = " << gradA_elem << "\n"); + UG_LOG("gradA_scale = " << gradA_scale << "\n"); + UG_LOG("areaTria = " << areaTria << "\n"); + UG_LOG("baseLineSquared = " << baseLineSquared << "\n"); + + UG_LOG("gradD_kVol = " << gradD_kVol << "\n"); + UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); + } + } + + ////////////////////////////////////////////////// + // (3.2) surface computations: + if ( rSH->get_subset_index(elem) == 4 ) + { + UG_LOG("elem subset index = 4:" << rSH->get_subset_index(elem) << "\n"); + + number gradD_kSurf = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); + + ////////////////////////////////////////////////////////// + // (4) add up all computations to entry of DoF-vector: + // gradD[Index] -= gradD_kSurf_x*(n-1)/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... + // gradD[numDoFs + Index] -= gradD_kSurf_y*(n-1)/(n*n); // ToDo! + DoFRef(u, vInd[0]) -= (-1.0) * gradD_kSurf/n; + if ( vInd[0][0] == 18 && cmp == 0 ) + { + UG_LOG("gradD_elem = " << gradD_elem << "\n"); + UG_LOG("gradA_elem = " << gradA_elem << "\n"); + UG_LOG("gradA_scale = " << gradA_scale << "\n"); + UG_LOG("areaTria = " << areaTria << "\n"); + UG_LOG("baseLineSquared = " << baseLineSquared << "\n"); + + UG_LOG("gradD_kSurf = " << gradD_kSurf << "\n"); + UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); + } + } + + + + UG_LOG("\n ---> v = " << v << " and Ind = " << Ind[v] << "\n"); + + }// end vrt-loop + + }// end cmp-loop + + } // end elem-loop + + // Attention: the factor 1/2 is removed from D_kVol AND D_kSurf, since it arises in both summands! + number functional = D_kVol/(n*n) - D_kSurf/n; + functional *= functional; + + return functional; + +} + +template +void MovingParticle:: +rescale_directions(const number functional, vector_type& u, SmartPtr > spApproxSpace, + SmartPtr > spMaster, const int topLevel) +{ + ///////////////////////////////////////////////// + // loop vertices and project directions + // of 'u' on outer boundary edges: + + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + DoFDistribution::traits::const_iterator iterBegin = dd->begin(); + DoFDistribution::traits::const_iterator iterEnd = dd->end(); + + // get subset handler + ConstSmartPtr rSH = dd->subset_handler(); + + number scaleFactor = sqrt(functional); + + // loop vertices + for(DoFDistribution::traits::const_iterator iter = iterBegin; iter != iterEnd; iter++) + { + // get vertex + Vertex* vrt = *iter; + + for (size_t cmp = 0; cmp < dim; ++cmp) + { + std::vector vInd; + if(dd->inner_dof_indices(vrt, cmp, vInd) != 1) + UG_THROW("1: error in inner_dof_indices operatio!\n"); + + DoFRef(u, vInd[0]) *= 2.0 * scaleFactor; + } + + + } // end vertices-loop + +} + +template +number MovingParticle:: +compute_max_step_size(SmartPtr > spApproxSpace, + SmartPtr > spMaster, const int topLevel) +{ + bool output = false; + + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + // get data + typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); + + // create Function Group + FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); + + // get subset handler + ConstSmartPtr rSH = dd->subset_handler(); + + // get iterators for all elems on subset + typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; + + typename DoFDistribution::traits::const_iterator iter, iterEnd; + iter = dd->begin(); + iterEnd = dd->end(); + + // loop elements in order to compute minimal edge size: + number minEdgeSize = 1000.0; + int N = 0; + for( ; iter != iterEnd; ++iter) + { + // get element + grid_base_object* elem = *iter; + + ////////////////////////////////////////////////// + // loop edges and collect associated vertices 'vrt1' and 'vrt2' and 'vrtOut: + std::vector vEdges; + CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); + for(size_t e = 0; e < vEdges.size(); ++e) + { + Edge* edge = vEdges[e]; + + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); + if ( vVertexEdge.size() != 2 ) + UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); + + number edgeSize = VecDistance(aaPos[vVertexEdge[0]], aaPos[vVertexEdge[1]]); + + std::vector vInd1; + if(dd->inner_dof_indices(vVertexEdge[0], 0, vInd1) != 1) + UG_THROW("1: error in inner_dof_indices operatio!\n"); + std::vector vInd2; + if(dd->inner_dof_indices(vVertexEdge[1], 0, vInd2) != 1) + UG_THROW("1: error in inner_dof_indices operatio!\n"); + + if ( vInd1[0][0] == 11 || vInd2[0][0] == 11 ) + { + if ( vInd1[0][0] == 4 || vInd2[0][0] == 4 ) + { + //UG_LOG("minEdgeSize = " << minEdgeSize << "\n"); + //UG_LOG("aaPos[vVertexEdge[0]] = " << aaPos[vVertexEdge[0]][0] << "\t" << aaPos[vVertexEdge[0]][1] << "\n"); + //UG_LOG("aaPos[vVertexEdge[1]] = " << aaPos[vVertexEdge[1]][0] << "\t" << aaPos[vVertexEdge[1]][1] << "\n"); + + } + } + + + if ( minEdgeSize > edgeSize ) + { + minEdgeSize = edgeSize; + + if ( output ) UG_LOG("minEdgeSize = " << minEdgeSize << "\n"); + } + else + { + if ( output ) UG_LOG("--> edgeSize = " << edgeSize << "\n"); + + } + + }// end edge-loop + N = N+1; + + if ( output ) UG_LOG("--> new element: " << N << "\n"); + + }// end elem-loop + + UG_LOG("1 -----------> minEdgeSize = " << minEdgeSize << "\n"); + + return minEdgeSize; +} + + +template +void MovingParticle:: +project_directions(const number functional, vector_type& u, SmartPtr > spApproxSpace, + SmartPtr > spMaster, const int topLevel) +{ + ///////////////////////////////////////////////// + // loop vertices and project directions + // of 'u' on outer boundary edges: + + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + DoFDistribution::traits::const_iterator iterBegin = dd->begin(); + DoFDistribution::traits::const_iterator iterEnd = dd->end(); + + // get subset handler + ConstSmartPtr rSH = dd->subset_handler(); + + size_t counter1 = 0; + size_t counter2 = 0; + size_t counter3 = 0; + size_t counter4 = 0; + size_t counter5 = 0; + size_t counter6 = 0; + + // loop vertices + for(DoFDistribution::traits::const_iterator iter = iterBegin; iter != iterEnd; iter++) + { + // get vertex + Vertex* vrt = *iter; + + ///////////////////////////////////////////////// + // (1) get direction to be projected: + MathVector project; + + for (size_t cmp = 0; cmp < dim; ++cmp) + { + std::vector vInd; + if(dd->inner_dof_indices(vrt, cmp, vInd) != 1) + UG_THROW("1: error in inner_dof_indices operatio!\n"); + + project[cmp] = DoFRef(u, vInd[0]); + } + + ///////////////////////////////////////////////// + // (2) project according to projection edge: + MathVector edge; + // (2.1) project onto x-coordinate: (1,0) + if ( rSH->get_subset_index(vrt) == 3 ) + { + edge[0] = 1.0; edge[1] = 0.0; + number scalar = VecProd(project, edge); + + VecScale(project, edge, scalar); + ++counter1; + //project[1] = 0.0; + } + // (2.2) project onto left-coordinate: (0.5,1) + else if ( rSH->get_subset_index(vrt) == 2 ) + { + edge[0] = 0.5; edge[1] = 1.0; + number scalar = VecProd(project, edge); + + VecScale(project, edge, scalar); + ++counter2; + } + + // (2.3) project onto x-coordinate: (-0.5,1) + else if ( rSH->get_subset_index(vrt) == 1 ) + { + edge[0] = -0.5; edge[1] = 1.0; + number scalar = VecProd(project, edge); + + VecScale(project, edge, scalar); + ++counter3; + } + // (2.4) corner may not moved at all: (0,0) + else if ( rSH->get_subset_index(vrt) == 5 ) + { + project[0] = project[1] = 0.0; + ++counter4; + } + else + { + ++counter5; + continue; + } + + ///////////////////////////////////////////////// + // (3) write projected direction back to data 'u': + + // REMARK: this part of code is only reached for vertices on the boundary!!! + // --> see counter5: continue! + for (size_t cmp = 0; cmp < dim; ++cmp) + { + std::vector vInd; + if(dd->inner_dof_indices(vrt, cmp, vInd) != 1) + UG_THROW("1: error in inner_dof_indices operatio!\n"); + + DoFRef(u, vInd[0]) = project[cmp]; + ++counter6; + + + } + + } // end vertices-loop + + UG_LOG("counter1 = " << counter1 << "\n"); + UG_LOG("counter2 = " << counter2 << "\n"); + UG_LOG("counter3 = " << counter3 << "\n"); + UG_LOG("counter4 = " << counter4 << "\n"); + UG_LOG("counter5 = " << counter5 << "\n"); + UG_LOG("counter6 = " << counter6 << "\n"); + +} + +template +number MovingParticle:: +gradient_descent(const size_t n, const number functional, const number bound, const number scaleAlpha, vector_type& u, SmartPtr > spApproxSpace, SmartPtr > spMaster, const int topLevel) +{ + // set dummy value in order to pass second while-loop at least once: + number functionalNew = functional; + + UG_LOG("-----------> functionalNew = " << functionalNew << "\n"); + + if ( !(fabs(functionalNew) > bound) ) + UG_THROW("attention: first time this condition neads to be satisfied!\n"); + + //while ( fabs(functionalNew) > bound ) + if ( 1 ) + { + number alpha = scaleAlpha*compute_max_step_size(spApproxSpace, spMaster, topLevel); + UG_LOG("2 -----------> alpha = " << alpha << "\n"); + + bool iterate = true; + // while ( iterate ) + if ( 1 ) + { + ///////////////////////////////////////////////// + // loop vertices and update coordinates: + + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + DoFDistribution::traits::const_iterator iterBegin = dd->begin(); + DoFDistribution::traits::const_iterator iterEnd = dd->end(); + + // create MultiindexProjector + std::vector multInd; + + typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); + + // loop vertices + for(DoFDistribution::traits::const_iterator iter = iterBegin; iter != iterEnd; iter++) + { + // get vertex + Vertex* vrt = *iter; + MathVector position = aaPos[vrt]; + + for (size_t cmp = 0; cmp < dim; ++cmp) + { + std::vector vInd; + if(dd->inner_dof_indices(vrt, cmp, vInd) != 1) + UG_THROW("1: error in inner_dof_indices operatio!\n"); + + ///////////////////////////////////////////////// + // (1) get gradient = update direction: + MathVector update; + update[cmp] = DoFRef(u, vInd[0]); + + ///////////////////////////////////////////////// + // (2) update position coordinates due to + // gradient direction and step size alpha: + aaPos[vrt][cmp] = position[cmp] + alpha * update[cmp]; + + UG_LOG("aaPos[vrt][" << cmp << "]: " << aaPos[vrt][cmp] << "\n"); + + }// end cmp-loop + + + } // end vertices-loop + + UG_LOG("vorher -----------> functionalNew = " << functionalNew << "\n"); + + functionalNew = compute_functional(n, u, spApproxSpace, spMaster, topLevel); + alpha = 0.5*alpha; + + if ( functionalNew < 0.0 ) iterate = true; + else iterate = false; + + UG_LOG("nachher -----------> functionalNew = " << functionalNew << "\n"); + + + }// end while-loop + + // ToDo: wie Verschiebumg von aaPos wieder Rückgängig machen bzw. altes Gitter zwischenspeichern? => auf Clone updaten? + + }// end while-loop + +} + + +}// end namespace MovingParticle +} // end namespace ug + + + +#endif /* MEAN_ID_H_ */ diff --git a/incompressible/fv1/moving_particle/moving_particle.h b/incompressible/fv1/moving_particle/moving_particle.h new file mode 100644 index 0000000..0075f7b --- /dev/null +++ b/incompressible/fv1/moving_particle/moving_particle.h @@ -0,0 +1,652 @@ +/* + * moving_particle.h + * + * Created on: 20.01.2015 + * Author: suze + */ + +#ifndef MOVING_PARTICLE_H_ +#define MOVING_PARTICLE_H_ + +#ifdef UG_PARALLEL + #include "lib_grid/parallelization/load_balancer_util.h" + #include "../../../../Parmetis/src/unificator_interface.h" + #include "lib_grid/grid/neighborhood.h" + #include "lib_grid/grid/neighborhood_util.h" // for GetConnectedNeighbor + #include "lib_grid/grid/grid_util.h" + #include "lib_grid/grid/grid.h" + #include "lib_grid/grid/grid_base_object_traits.h" // for geometry_traits +#endif + +#include "../../incompressible_navier_stokes_base.h" + +#include "lib_disc/spatial_disc/immersed_util/interface_handler/interface_handler_flat_top_cut/interface_handler_particle.h" +#include "loc_to_glob_mapper_particle.h" +#include "immersed_bnd_cond_particle.h" + +// for method 'mark_collision_area()': +#include "lib_grid/refinement/adaptive_regular_mg_refiner.h" + +#include +#include + + +namespace ug{ +namespace NavierStokes{ + + + +template < typename TDomain, typename TAlgebra> +class MovingParticle + : public IMovingInterface +{ + public: + /// world Dimension + static const int dim = TDomain::dim; + + /// Algebra type + typedef TAlgebra algebra_type; + + /// Type of algebra matrix + typedef typename algebra_type::matrix_type matrix_type; + + /// Type of algebra vector + typedef typename algebra_type::vector_type vector_type; + + typedef typename domain_traits::grid_base_object grid_base_object; + + MovingParticle(SmartPtr > ass, + SmartPtr > spMaster, + SmartPtr > cutElementHandler, + number fluidDensity, number fluidKinVisc); + + SmartPtr > get_BndCond() { return m_spInterfaceBndCond; } + + // SmartPtr > get_particles() { return m_spParticleHandlerGlobal->get_particles(); } + + void set_gravity(bool gravity, number gravityConst) { m_spInterfaceMapper->set_gravity(gravity, gravityConst); } + void set_repulsive_force(bool repForce, number forceValue) { m_spInterfaceMapper->set_repulsive_force(repForce, forceValue); } + void set_glowinski_repulsive_force(bool maxRepForce, number rho, number eps) { m_spInterfaceMapper->set_glowinski_repulsive_force(maxRepForce, rho, eps); } + void set_minimum_correction_force(bool EquiRepForce, number repulsiveDistance) { m_spInterfaceMapper->set_minimum_correction_force(EquiRepForce, repulsiveDistance); } + + void set_time_step(number dt) { m_spInterfaceMapper->set_time_step(dt); } + void set_volume_comp_mode(bool bVolumeCompMode) { m_spInterfaceMapper->set_volume_comp_mode(bVolumeCompMode); } + + void set_StdFV_assembling(bool bValue) { m_spInterfaceHandlerLocal->set_StdFV_assembling(bValue);} + bool StdFV_assembling() { return m_spInterfaceHandlerLocal->StdFV_assembling(); } + + + // destructor + ~MovingParticle(){}; + + /// called via .lua: + void init(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel) + { +// UG_LOG("initialize on process " << pcl::ProcRank() << "\n"); + + m_spApproxSpace = spApproxSpace; + + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + m_spParticleHandlerGlobal->template init(dd, baseLevel, topLevel); + // => update_multigrid_data() for all given levels + + // transfer direction: m_vvLinearVelocity/m_vvAngularVelocity ---> DoFRef(u, transInd) + // --> if particle velocities are FREE: m_vvLinearVelocity/m_vvAngularVelocity are initialized + // during ParticleProvider:adfd() with 0.0 => ok and INDEPENDENT of FREE or MOVING modus + update_particle_solution(u, topLevel); + } + + number MeanElementDiameter(TDomain& domain, int level); + void set_element_diameter(double val) { m_spInterfaceMapper->set_element_diameter(val); } + + ////////////////////////////////////////////////////////////////////////////////// + // ---> .lua: update(u, deltaT, u:grid_level()): update global indices (transInd...) + // => A. copy_solution(topLev) + // B. update(baseLev-topLev) + // C. update_solution(topLev) + ////////////////////////////////////////////////////////////////////////////////// + // write solution to nodes outside fluid with particle velocities + // --> call method vie .lua BEFORE 'solTimeSeries:push_discard_oldest(oldestSol, time)': + // => in case that outside nodes are inside AFTER update_prtCoords: NO solution defined here! + void update(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel, const number time, const number deltaT) + { + int topLev = spApproxSpace->num_levels()-1; + if ( topLev != topLevel ) + UG_THROW("NavierStokes::update: parameter 'topLevel' = " << topLevel << " != " + << topLev << "current top leven! \n"); + + // A. copy solution to data: DoFRef(u, transInd/rotInd) ---> m_vvLinearVelocity/m_vvAngularVelocity + // reverse direction done during 'NavierStokes::update_particle_solution()' + copy_particle_solution(u, topLevel); + + // B. synchronize particle data when everything in ParticleProvider is up to date. +#ifdef UG_PARALLEL + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + m_spParticleHandlerGlobal->synchronize_particles(levIndex); +#endif + // C. calculate new particle coordinates + m_spParticleHandlerGlobal->update_prtCoords(topLevel, deltaT); + + // D. fill particle nodes with their real solution + // --> FIRST copy_particle_solution() necessary, since eventually during + // fill extraDoF-nodes will be overwriten + fill_particle_solution(u, topLevel, time); + + // E. update data => new node for (u, transInd) ! + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + m_spParticleHandlerGlobal->template init(dd, baseLevel, topLevel); + + // F. update solution from data: m_vSolTransDoFRef(u, transInd/rotInd) + // transfer direction: m_vvLinearVelocity/m_vvAngularVelocity ---> DoFRef(u, transInd) + update_particle_solution(u, topLevel); + + // reset volume: + m_spInterfaceMapper->reset_volume(); + } + + void get_velocity(MathVector& transSol, MathVector& rotSol, const vector_type& u, const int topLevel, number deltaT, const size_t prtIndex); +#ifdef UG_PARALLEL + void pre_balancing_update(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel, const number time, number deltaT) + { + int topLev = spApproxSpace->num_levels()-1; + if ( topLev != topLevel ) + UG_THROW("NavierStokes::update: parameter 'topLevel' = " << topLevel << " != " + << topLev << "current top leven! \n"); + + const char* filename = "update_times"; + std::string name(filename); + char ext[50]; + sprintf(ext, "_%d.txt", pcl::ProcRank()); + //sprintf(ext, ".txt"); + name.append(ext); + FILE* outputFile = fopen(name.c_str(), "a"); + + std::clock_t begin = std::clock(); + // A. copy solution to data: DoFRef(u, transInd) ---> m_vSolTrans + // reverse direction done during 'NavierStokes::update_particle_solution()' + copy_particle_solution(u, topLevel); + std::clock_t end = std::clock(); + fprintf(outputFile,"copy_particle_solution %f", double(end - begin) / CLOCKS_PER_SEC); + + begin = std::clock(); + + // C. calculate new particle coordinates + m_spParticleHandlerGlobal->update_prtCoords(topLevel, deltaT); + end = std::clock(); + fprintf(outputFile,"update_prtCoords %f", double(end - begin) / CLOCKS_PER_SEC); + + begin = std::clock(); + // B. synchronize particle data when everything in ParticleProvider is up to date. + + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + m_spParticleHandlerGlobal->synchronize_particles(levIndex); + + end = std::clock(); + fprintf(outputFile,"synchronize_particles %f", double(end - begin) / CLOCKS_PER_SEC); + + begin = std::clock(); + + // D. fill particle nodes with their real solution + // --> FIRST copy_particle_solution() necessary, since eventually during + // fill extraDoF-nodes will be overwriten + fill_particle_solution(u, topLevel, time); + end = std::clock(); + fprintf(outputFile,"fill_particle_solution %f", double(end - begin) / CLOCKS_PER_SEC); + + fclose(outputFile); + + } + + void post_balancing_update(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel, const number time, number deltaT) + { + // E. update data => new node for (u, transInd) ! + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + m_spParticleHandlerGlobal->template init(dd, baseLevel, topLevel); + + // F. update solution from data: m_vSolTransDoFRef(u, transInd) + // transfer direction: m_vSolTrans ---> DoFRef(u, transInd) + update_particle_solution(u, topLevel); + + // reset volume: + m_spInterfaceMapper->reset_volume(); + } +#endif + + void compute_gradient_local_max(vector_type& sol, vector_type& grad,SmartPtr > spApproxSpace, const int topLevel); + + /// call of the method via lua to set the real velocity values within the particle domain + void adjust_global_solution(vector_type& u, const int topLevel); + + void fill_particle_solution(vector_type& u, const int topLevel, const number time); + + /// transfer direction: DoFRef(u, transInd) ---> m_vSolTrans + void copy_particle_solution(vector_type& u, const int topLevel); + + /// transfer direction: m_vSolTrans ---> DoFRef(u, transInd) + void update_particle_solution(vector_type& u, const int topLevel); + + void initialize_threshold(TDomain& domain, const int baseLevel, const int topLevel); + + /// checks if grid data is updated and returns 'levIndex'-pair for 'gridLevel' in 'm_Map' + int get_Index(const GridLevel& gridLevel) + { + ConstSmartPtr dd = m_spApproxSpace->dof_distribution(gridLevel); + + const int levIndex = m_spParticleHandlerGlobal->get_Index(gridLevel, dd); + + return levIndex; + } + + // void clear_solution(SmartPtr > vSol, const GridLevel& topGrid); + void clear_solution(vector_type& u, const int topLevel); + /// see ParticleConstraint::adjust_solution() +// void update_solution(SmartPtr > vSol, const GridLevel& topGrid); + + bool is_time_dependent() { return m_spInterfaceMapper->is_time_dependent();} + +number compute_functional_fixed(const size_t n, vector_type& u, SmartPtr > spApproxSpace, SmartPtr > spMaster, const int topLevel); + +number compute_functional_combined(const size_t n, vector_type& u, SmartPtr > spApproxSpace, SmartPtr > spMaster, const int topLevel); + +number compute_functional(const size_t n, vector_type& u, SmartPtr > spApproxSpace, SmartPtr > spMaster, const int topLevel); +number compute_functional_all(const size_t n, vector_type& u, SmartPtr > spApproxSpace, SmartPtr > spMaster, const int topLevel); + +number compute_max_step_size(SmartPtr > spApproxSpace, + SmartPtr > spMaster, const int topLevel); +number gradient_descent(const size_t n, const number functional, const number bound, const number scaleAlpha, vector_type& u, SmartPtr > + spApproxSpace, SmartPtr > spMaster, const int topLevel); +void project_directions(const number functional, vector_type& u, SmartPtr > spApproxSpace, + SmartPtr > spMaster, const int topLevel); +void rescale_directions(const number functional, vector_type& u, SmartPtr > spApproxSpace, + SmartPtr > spMaster, const int topLevel); + + + /// helper functions for compute_error_on_circle() + void interpolate_point(ConstSmartPtr dd, const vector_type& u, + const MathVector& evalPos, MathVector& interpolation); +// void compute_error_on_circle(const vector_type& u, const int topLevel, number radius); + + void print_deltaP(const vector_type& u, const int topLevel); + void print_pressure(const vector_type& u, const int topLevel); + void print_pressure_nodal(const vector_type& u, const int topLevel); + + /// writing data to file; called via .lua + void print_velocity(const vector_type& u, const int topLevel, number time, const char* filename); + // void print_velocity_many_particles(const vector_type& u, const int topLevel, number time, const char* filename); + + bool mark_collision_area(SmartPtr refiner, int level); + double estimate_repulsive_force_parameters(vector_type& u, int topLevel, double MaxElemDiameter, double deltaT); + + void set_forceLog(bool val) { + m_spInterfaceMapper->set_forceLog(val); + } + + void set_mpi_routine(int val){ + m_spParticleHandlerGlobal->set_mpi_routine(val); + } + + private: + // new member + SmartPtr > m_spParticleHandlerGlobal; + SmartPtr > m_spInterfaceHandlerLocal; + + // member from base class + SmartPtr > m_spInterfaceMapper; // contains member of class 'IInterfaceHandlerLocal' + SmartPtr > m_spInterfaceBndCond; // contains member of class 'IInterfaceHandlerLocal' + + /// current ApproxSpace + SmartPtr > m_spApproxSpace; + + +}; + + +#ifdef UG_PARALLEL + template + class ParticleUnificator : public parmetis::IUnificator::base_obj_type> + { + public: + typedef typename GeomObjBaseTypeByDim::base_obj_type elem_t; + typedef typename elem_t::side side_t; + typedef Attachment AElemIndex; + typedef Attachment > AElemIndices; + + /// world Dimension + static const int dim = TDomain::dim; + + /// Type of position coordinates + typedef MathVector position_type; + + /// Type of Position Attachment + typedef Attachment position_attachment_type; + + /// Type of Accessor to the Position Data Attachment + typedef Grid::VertexAttachmentAccessor + position_accessor_type; + + /// constructor + ParticleUnificator(SmartPtr spDom) + : m_spMG(spDom->grid().operator->()) + { + // get position attachment + m_aPos = GetDefaultPositionAttachment(); + + // let position accessor access Vertex Coordinates + if(!m_spMG->has_attachment(m_aPos)) + m_spMG->attach_to(m_aPos); + m_aaPos.access(*m_spMG, m_aPos); + } + + void update_particles(SmartPtr > provider ) + { + m_vParticleCoord.clear(); + + size_t numPrt = provider->num_particles(); + for ( size_t i = 0; i < numPrt; ++i ) + m_vParticleCoord.push_back(std::make_pair(provider->get_radius(i), provider->get_center(i))); + + UG_LOG("in update_particles:\n") + for ( size_t i = 0; i < m_vParticleCoord.size(); ++i ) + UG_LOG("m_vParticleCoord: " << m_vParticleCoord[i].second << "\n"); + + UG_LOG("in update_particles end....\n\n\n"); + + } + + virtual void unify( + MultiGrid* mg, + int lvl, + int localOffset, + const Grid::AttachmentAccessor& aaElemInd, // local indices! + const Grid::AttachmentAccessor& aaSideElemInd, // global indices! + std::vector >& unificationPairs) const // global indices! + { + const DistributedGridManager& dgm = *mg->distributed_grid_manager(); + + std::vector vNeighbors; + + //UG_LOG("unify() on lvl " << lvl << "\n"); + + typename geometry_traits::iterator iterEnd, iter; + iter = mg->begin(lvl); + iterEnd = mg->end(lvl); + + // iterate all elements + for(; iter != iterEnd; ++iter) { + elem_t* elem = *iter; + + int locInd = aaElemInd[elem]; + + //UG_LOG("element is " << locInd << "..\n"); + + // skip ghosts + if (locInd == -1) { + continue; + } + + // only process particle elements. + if (is_PartOfParticle(elem)) { + //UG_LOG("local index is " << locInd << " and global index is " << locInd + localOffset << "\n"); + + //std::vector sides; + typename Grid::traits::secure_container sides; + //CollectAssociated(sides, *mg, elem, true); + mg->associated_elements(sides, elem); + //UG_LOG("sides has length " << sides.size() << "\n"); + // iterate over current element's sides + for (size_t i = 0; i < sides.size(); ++i) { + //UG_LOG("Check side between elements " << aaSideElemInd[sides[i]][0] << " and " << aaSideElemInd[sides[i]][1] << ".\n"); + // check if neighbor on the other side is stored on another process + // if not use aaElemInd with local indices + if (!dgm.is_in_horizontal_interface(sides[i])) // QUESTION: Check elem_t or side_t here? + { + // get neighbors of element + //CollectNeighbors(vNeighbors, elem, *mg); + + // iterate over neighbor elements + /*for (elem_t* neighbor : vNeighbors) { + + // check if neighbor element is inside particle too + if (is_PartOfParticle(neighbor)) { + UG_LOG("Add " << aaElemInd[elem]+localOffset << "(" << localOffset << ") and " << aaElemInd[neighbor]+localOffset << " to unificationPairs\n"); + unificationPairs.push_back(std::make_pair(aaElemInd[elem] + localOffset, aaElemInd[neighbor] + localOffset)); + } + }*/ + + // get back the elements to current side and add them to unificationPairs + typename Grid::traits::secure_container elemList; + mg->associated_elements(elemList, sides[i]); + UG_COND_THROW(elemList.size() > 2, "More than two " << elemList[0]->reference_object_id() + << "s associated with " << sides[i]->reference_object_id() << "."); + + if (elemList.size() == 2) + { + int locInd0 = aaElemInd[elemList[0]]; + int locInd1 = aaElemInd[elemList[1]]; + + // exclude ghosts + if (locInd0 == -1 || locInd1 == -1) + continue; + + // add to unification pairs + //UG_LOG("(1) Add " << locInd0+localOffset << "(" << localOffset << ") and " << locInd1+localOffset << " to unificationPairs\n"); + unificationPairs.push_back(std::make_pair(locInd0+localOffset, locInd1+localOffset)); + } else { + //UG_LOG("elemList.size() = " << elemList.size() << " != 2 shouldn't appear.\n"); + } + } + // if other processes have to be addressed for neighbors, use aaSideElemInd with global indices instead + else{ + //UG_LOG("Elements on different processes\n"); + const std::vector& inds = aaSideElemInd[sides[i]]; + + // if element side is part of global boundary aaSideElemInd[elem] holds only the element itself. + if (inds.size() == 1) + continue; + + UG_ASSERT(inds.size() == 2, "Indices attachment vector has more or less than 2 entries."); + //UG_LOG("(2) Add " << inds[0] << " and " << inds[1] << " to unificationPairs\n"); + unificationPairs.push_back(std::make_pair(inds[0], inds[1])); + } + } + } + } + //UG_LOG("unify() finished.\n"); + } + + /** + * Function that estimates if any particle is close to any process border. + */ + bool rebalance(MultiGrid* mg, int lvl){ + typename geometry_traits::iterator iterEnd, iter; + iter = mg->begin(lvl); + iterEnd = mg->end(lvl); + + int repart = 0; + + // iterate over all elements + for(; iter != iterEnd; ++iter) { + elem_t* elem = *iter; + typename Grid::traits::secure_container sides; + mg->associated_elements(sides, elem); + + // iterate over current element's sides + for (size_t i = 0; i < sides.size(); ++i) { + // get back the elements to current side and add them to unificationPairs + typename Grid::traits::secure_container elemList; + mg->associated_elements(elemList, sides[i]); + // if border element + // UG_LOG("elemList.size(): " << elemList.size()) + if (elemList.size() < 2) { + if (is_PartOfParticle(elemList[0])) { + repart = 1; + } + } + } + } + + pcl::ProcessCommunicator com; + int repart_all = 0; + com.allreduce(&repart, &repart_all, 1, MPI_INT, PCL_RO_SUM); + + return repart_all; + } + + private: + bool is_PartOfParticle(elem_t* elem) const + { + bool part = false; + for (size_t p = 0; p < m_vParticleCoord.size(); ++p) { + // special case if particle is smaller than one element of the multigrid's base level -> ist das überhaupt relevant? kann ein Baselevelelement partitioniert werden? + if (ContainsPoint(elem, m_vParticleCoord[p].second, m_aaPos)) { + //UG_LOG("Particle center is inside this element.\n"); + return true; + } + // check if at least one vertex is inside particle + for(size_t i = 0; i < elem->num_vertices(); ++i) { + if (is_insideParticle(elem->vertex(i),p)) { + return true; + } + } + // // exclude triangle-circle overlap + // for(size_t i = 0; i < elem->num_vertices(); ++i) { + // for(size_t j = i; j < elem->num_vertices(); ++j) { + // if (intersection(m_vParticleCoord[p].second,m_vParticleCoord[p].first,m_aaPos[elem->vertex(i)],m_aaPos[elem->vertex(j)])) { + // return true; + // } + // } + // } + + MathVector elemCenter = m_aaPos[elem->vertex(0)]; + for(size_t i = 1; i < elem->num_vertices(); ++i) { + // const MathVector& vrtPos = m_aaPos[elem->vertex(i)]; + // for (size_t j = 0; j < dim; ++j) { + // elemCenter[j] += vrtPos[j]; + // } + elemCenter += m_aaPos[elem->vertex(i)]; + } + elemCenter /= elem->num_vertices(); + //UG_LOG("Element Center is (" << elemCenter[0] << ", " <num_vertices(); ++i) { + number distance = VecDistance(m_aaPos[elem->vertex(i)],elemCenter); + maxDistance = (maxDistance > distance) ? maxDistance : distance; + } + //UG_LOG("maxDistance is " << maxDistance << ".\n"); + const number radius = m_vParticleCoord[p].first; + const MathVector& center = m_vParticleCoord[p].second; + number centerDistance = VecDistance(elemCenter, center); + //UG_LOG("centerDistance is " << centerDistance << ".\n"); + part = (part or (radius + maxDistance > centerDistance)); + } + return part; + //return false; + } + + bool is_insideParticle(Vertex* vrt, size_t prtIndex) const + { + // get distance to first radius as initial value + const MathVector& vrtPos = m_aaPos[vrt]; + const MathVector& center = m_vParticleCoord[prtIndex].second; + const number radius = m_vParticleCoord[prtIndex].first; + + if (VecDistance(vrtPos, center) <= radius) { + return true; + } + return false; //set_nearInterface(vrt, prtIndex); + } + + bool is_outside(Vertex* vrt) + { + // loop over all centers and pick the index with minimal distance + for (size_t p = 0; p < m_vParticleCoord.size(); ++p) + if ( !is_insideParticle(vrt, p) ) + return true; + return false; + } + + bool conn_is_cut_by_interface(side_t* conn) + { + // init data + bool insideFluid = false; + bool outsideFluid = false; + + // loop vertices + for(size_t i = 0; i < conn->num_vertices(); ++i) + { + // check if inside a particle + if (is_outside(conn->vertex(i))) outsideFluid = true; + else insideFluid = true; + + //if (insideFluid && is_nearInterface(vrt)) + // UG_THROW("in 'get_elem_modus()': case 'set_nearInterface(vrt) = true' not possible!\n"); + + } // vertex loop + + // return elem type + if (insideFluid && outsideFluid) { + return true; + //UG_LOG("edge " << conn->grid_data_index() << " should have weight " << m_weight); + } + return false; + + } + + bool intersection(MathVector center, double radius, MathVector vertex1, MathVector vertex2) const { + number alpha; + + MathVector lineDir; + MathVector rayDir; + // lineDir = vertex1 - vertex2; + VecSubtract(lineDir, vertex1, vertex2); + // rayDir = vertex2 - center; + VecSubtract(rayDir, vertex2, center); + + const number a = VecDot(lineDir, lineDir); + const number b = 2.0 * VecDot(lineDir, rayDir); + const number c = VecDot(vertex2, vertex2) + VecDot(center, center) + - 2 * VecDot(vertex2, center) - radius * radius; + + const number discriminant = b * b - 4 * a * c; + + // check that 'vrtPosOut' and 'vrtPosIn' really lie on different sides of the circle: + //if (discriminant < -1e-8) + // UG_LOG("discriminant is " << discriminant << " < -1e-8\n"); + //UG_THROW("Value of discriminant = " << discriminant << "\n"); + + // discriminant = 0! + //const number alpha1 = (-b - sqrt(discriminant)) / (2.0 * a); + //const number alpha2 = (-b + sqrt(discriminant)) / (2.0 * a); + + // if (alpha1 <= alpha2) + // alpha = alpha1; + // else + // alpha = alpha2; + + if (discriminant < 0) + return false; + else + return true; + } + + SmartPtr m_spMG; + position_attachment_type m_aPos; /// > > m_vParticleCoord; + }; + +#endif + +} // end namespace MovingParticle +} // end namespace ug + + +#include "moving_particle_impl.h" +#include "moving_particle_tools.h" +#include "meanID_tools.h" + + + +#endif /* MOVING_PARTICLE_H_ */ diff --git a/incompressible/fv1/moving_particle/moving_particle_impl.h b/incompressible/fv1/moving_particle/moving_particle_impl.h new file mode 100644 index 0000000..683fae6 --- /dev/null +++ b/incompressible/fv1/moving_particle/moving_particle_impl.h @@ -0,0 +1,913 @@ +/* + * moving_particle_impl.h + * + * Created on: 20.01.2015 + * Author: suze + */ + +#ifndef MOVING_PARTICLE_IMPL_H_ +#define MOVING_PARTICLE_IMPL_H_ + +#include + +namespace ug { +namespace NavierStokes { + + +/////////////////////////////////////////////////////////// +// Implementation of the methods class +// 'MovingParticle' +/////////////////////////////////////////////////////////// + +template +MovingParticle::MovingParticle( + SmartPtr > ass, + SmartPtr > spMaster, + SmartPtr > cutElementHandler, + number fluidDensity, number fluidKinVisc) : + m_spParticleHandlerGlobal(cutElementHandler), + m_spInterfaceHandlerLocal( + new InterfaceHandlerLocalParticle(cutElementHandler, fluidDensity, fluidKinVisc) ), + m_spInterfaceMapper( + new ParticleMapper(m_spInterfaceHandlerLocal)), + m_spInterfaceBndCond( + new ParticleBndCond(spMaster, m_spInterfaceHandlerLocal)) +{ + + if (cutElementHandler->num_particles() == 0) + UG_THROW("MovingParticle::Constructor(): no particles initializen in 'cutElementHandler\n"); + + // initialize singleton and set local handler + typedef DimFV1FTGeometry > TFVGeom; + TFVGeom& geo = GeomProvider::get(LFEID(LFEID::LAGRANGE, dim, 1), 1); + geo.set_interface_handler(m_spInterfaceHandlerLocal); + +// initialize mapper within domainDisc: + SmartPtr > assAdapt = ass->ass_tuner(); + assAdapt->set_mapping(m_spInterfaceMapper.get()); + assAdapt->enable_modify_solution(true); + + + // => assTuner->modify_LocSol() = mapper->modify_LocSol() + // see: ass_tuner.h: 114 + + // ToDo: reconstruct modify_LocSol: ??? + // assAdapt->set_local_modifier(); + +} + +/* + template + void MovingParticle:: + clear_solution(SmartPtr > vSol, const GridLevel& topGrid) + { + //approxSpace->dof_distribution(GridLevel(GridLevel::TOP, GridLevel::SURFACE)), time); + + } + */ + +template +number MovingParticle::MeanElementDiameter(TDomain& domain, + int level) { + typedef typename domain_traits::grid_base_object TElem; + + //typedef typename std::vector::iterator ListIter; + typedef typename geometry_traits::iterator ListIter; + + ListIter iter = domain.grid()->template begin(level); + ListIter iterEnd = domain.grid()->template end(level); + + number mean = 0.0; + size_t numIter = 0; + for (; iter != iterEnd; ++iter) { + mean += ElementDiameterSq(*domain.grid(), domain.position_accessor(), + *iter); + numIter++; + } + + mean = mean / numIter; + UG_LOG("mean = " << std::sqrt(mean) << "\n"); + +#ifdef UG_PARALLEL + // share value between all procs + pcl::ProcessCommunicator com; + // ToDO: PCL_RO_MIN oder MAX oder doch mean noch berechnen m.H.v. /numProcs??? + //UG_THROW("in MeanElementDiameter(): was macht 'allredue' im Parallelen???\n"); + mean = com.allreduce(mean, PCL_RO_MIN); +#endif + + UG_LOG("nach com.allreduce: mean = " << std::sqrt(mean) << "\n"); + return std::sqrt(mean); +} + +template +void MovingParticle::initialize_threshold(TDomain& domain, + const int baseLevel, const int topLevel) { + UG_LOG("----------------- START initialize_threshold() ---------------- \n"); + + if (baseLevel < 0) + UG_THROW( + "initialize_threshold(): no cast of baselevel from 'int' tp 'size_t' possible! \n"); + if (topLevel < 0) + UG_THROW( + "initialize_threshold(): no cast of toplevel from 'int' tp 'size_t' possible! \n"); + + typedef typename domain_traits::grid_base_object TElem; + +// compute level-dependent value for threshold: + for (size_t lev = baseLevel; lev <= (size_t) topLevel; ++lev) { + const number maxLength = MaxElementDiameter(domain, lev); + const number meanLength = MeanElementDiameter(domain, lev); + UG_LOG("maxLength = " << maxLength << "\n"); + UG_LOG("meanLength = " << meanLength << "\n"); + UG_LOG("threshold_max = " << maxLength*maxLength << "\n"); + UG_LOG("threshold_mean = " << meanLength*meanLength << "\n"); + + m_spParticleHandlerGlobal->set_threshold(lev, meanLength * meanLength); + //m_spParticleHandlerGlobal->set_threshold(lev, 0.003); + + } + + UG_LOG("----------------- END initialize_threshold() ---------------- \n"); + +} + +template +void MovingParticle:: +get_velocity(MathVector& transSol, MathVector& rotSol, const vector_type& u, const int topLevel, number deltaT, const size_t prtIndex) +{ + UG_LOG("MovingParticle::print_velocity(): Start: \n"); + + size_t numPrt = m_spParticleHandlerGlobal->num_particles(); + + // if ( numPrt > 2 ) + // UG_THROW("Particle:output_velocity: VORSICHT, output nicht implementiert fuer mehr als 2 particle! -> m_bShared[][] ist Problem! ... Exit! \n"); + + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + + +#ifdef UG_PARALLEL + std::vector ElemList = m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][prtIndex]; + UG_LOG("1 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << "\n"); + if (ElemList.size() == 0) { + UG_LOG("2 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + return; + } +#endif + // get multiindices for translation and rotation of particle + std::vector < DoFIndex > transInd = m_spParticleHandlerGlobal->get_transInd(levIndex, prtIndex); + std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd(levIndex, prtIndex); + + + for ( int d = 0; d < dim; ++d ) + { + transSol[d] = DoFRef(u, transInd[d]); + rotSol[d] = DoFRef(u, rotInd[d]); + UG_LOG("in get_velocity: transSol: " << transSol[d] << "\t rotSol: " << rotSol[d] << "\n"); + } + + + +} + + +// transfer direction: DoFRef(u, transInd) ---> m_vvLinearVelocity/m_vvAngularVelocity +template +void MovingParticle::copy_particle_solution(vector_type& u, + const int topLevel) { + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + + for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + +#ifdef UG_PARALLEL + std::vector ElemList = + m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + UG_LOG( + "1 MovingParticle::copy_solution: ElemList.size(): " << ElemList.size() << "\n"); + if (ElemList.size() == 0) { + UG_LOG( + "2 MovingParticle::copy_solution: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + continue; + } +#endif +#ifdef UG_DEBUG + UG_LOG( + "copy_solution(): VORHER transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); + UG_LOG( + "copy_solution(): VORHER transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); + UG_LOG( + "copy_solution(): VORHER rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); + UG_LOG( + "copy_solution(): VORHER rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); +#endif + // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) + std::vector < DoFIndex > transInd = + m_spParticleHandlerGlobal->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd( + levIndex, p); + + UG_LOG(" transInd(0) = " << transInd[0] << "\n"); + UG_LOG(" rotInd(0) = " << rotInd[0] << "\n"); + + for (int d = 0; d < dim; ++d) { + number solution = DoFRef(u, transInd[d]); + m_spParticleHandlerGlobal->set_extraSolTrans(solution, p, 0, d); + DoFRef(u, transInd[d]) = 0.0; + + solution = DoFRef(u, rotInd[d]); + m_spParticleHandlerGlobal->set_extraSolRot(solution, p, 0, d); + DoFRef(u, rotInd[d]) = 0.0; + } +#ifdef UG_DEBUG + UG_LOG( + "copy_solution(): NACHHER transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); + UG_LOG( + "copy_solution(): NACHHER transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); + UG_LOG( + "copy_solution(): NACHHER rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); + UG_LOG( + "copy_solution(): NACHHER rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); +#endif + } // end particle loop + +} + +template +void MovingParticle::compute_gradient_local_max( + vector_type& sol, vector_type& grad, + SmartPtr > spApproxSpace, + const int topLevel) { + +// get data + typedef typename domain_traits::grid_base_object grid_base_object; + typename DoFDistribution::traits::const_iterator iter, + iterEnd; + + ConstSmartPtr dd = spApproxSpace->dof_distribution( + GridLevel(topLevel, GridLevel::LEVEL)); + typename TDomain::position_accessor_type aaPos = + m_spParticleHandlerGlobal->m_aaPos; + + iter = dd->template begin(); + iterEnd = dd->template end(); + + // loop elements in order to compute the volume and set rhs: + for (; iter != iterEnd; iter++) { + // get element + grid_base_object* elem = *iter; + + if (m_spParticleHandlerGlobal->m_spOutsideMarker->is_marked(elem)) + continue; + + std::vector < DoFIndex > vInd1; + std::vector < DoFIndex > vInd2; + + std::vector vEdges; + CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); + + if (m_spParticleHandlerGlobal->m_spCutMarker->is_marked(elem)) { + for (size_t e = 0; e < vEdges.size(); ++e) { + Edge* edge = vEdges[e]; + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, + edge); + if (vVertexEdge.size() != 2) + UG_THROW( + "error in collecting vertices associated to an edge!....EXIT!...\n"); + + Vertex* vrt1 = vVertexEdge[0]; + Vertex* vrt2 = vVertexEdge[1]; + + // no gradient needs to be computed on outside edges: + if (m_spInterfaceHandlerLocal->is_FTVertex(vrt1) + && m_spInterfaceHandlerLocal->is_FTVertex(vrt2)) + continue; + + if (dd->inner_dof_indices(vrt1, dim, vInd1) != 1) + UG_THROW( + "MovingParticle::compute_gradient(): Only one index expected."); + if (dd->inner_dof_indices(vrt2, dim, vInd2) != 1) + UG_THROW( + "MovingParticle::compute_gradient(): Only one index expected."); + + // compute local gradient along the edge + // UG_LOG("DoFRef(sol,vInd1[0]): " << DoFRef(sol,vInd1[0]) << "\n"); + // UG_LOG("DoFRef(sol,vInd2[0]): " << DoFRef(sol,vInd2[0]) << "\n"); + + number grad_edge = fabs( + DoFRef(sol, vInd1[0]) - DoFRef(sol, vInd2[0])); + number edgeLength = VecDistance(aaPos[vrt1], aaPos[vrt2]); + + if (!m_spInterfaceHandlerLocal->is_FTVertex(vrt1) + && !m_spInterfaceHandlerLocal->is_FTVertex(vrt2)) { // nothing has to be adapted! + } else if (m_spInterfaceHandlerLocal->is_FTVertex(vrt1)) { + if (m_spInterfaceHandlerLocal->is_FTVertex(vrt2)) + UG_THROW("hmmm...wrong in 'compute_gradient()'...\n"); + + // compute intersectionPoint: + MathVector intersectionPnt; + if (m_spInterfaceHandlerLocal->is_nearInterfaceVertex(vrt1)) + VecCopy(intersectionPnt, aaPos[vrt1], 0.0); + else + m_spInterfaceHandlerLocal->get_intersection_point( + intersectionPnt, vrt2, vrt1); + + // compute edgeLength: + edgeLength = VecDistance(aaPos[vrt2], intersectionPnt); + } else if (m_spInterfaceHandlerLocal->is_FTVertex(vrt2)) { + if (m_spInterfaceHandlerLocal->is_FTVertex(vrt1)) + UG_THROW("hmmm...wrong in 'compute_gradient()'...\n"); + + // compute intersectionPoint: + MathVector intersectionPnt; + if (m_spInterfaceHandlerLocal->is_nearInterfaceVertex(vrt2)) + VecCopy(intersectionPnt, aaPos[vrt2], 0.0); + else + m_spInterfaceHandlerLocal->get_intersection_point( + intersectionPnt, vrt1, vrt2); + // compute edgeLength: + edgeLength = VecDistance(aaPos[vrt1], intersectionPnt); + } + + grad_edge = grad_edge / edgeLength; + // set local maximum over all gradients along the edge to a given vertex + DoFRef(grad, vInd1[0]) = std::max(DoFRef(grad, vInd1[0]), + grad_edge); + DoFRef(grad, vInd2[0]) = std::max(DoFRef(grad, vInd2[0]), + grad_edge); + + } // end edge-loop + } else { + for (size_t e = 0; e < vEdges.size(); ++e) { + Edge* edge = vEdges[e]; + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, + edge); + if (vVertexEdge.size() != 2) + UG_THROW( + "error in collecting vertices associated to an edge!....EXIT!...\n"); + + Vertex* vrt1 = vVertexEdge[0]; + Vertex* vrt2 = vVertexEdge[1]; + if (dd->inner_dof_indices(vrt1, dim, vInd1) != 1) + UG_THROW( + "MovingParticle::compute_gradient(): Only one index expected."); + if (dd->inner_dof_indices(vrt2, dim, vInd2) != 1) + UG_THROW( + "MovingParticle::compute_gradient(): Only one index expected."); + + // compute local gradient along the edge + number edgeLength = VecDistance(aaPos[vrt1], aaPos[vrt2]); + number grad_edge = fabs( + DoFRef(sol, vInd1[0]) - DoFRef(sol, vInd2[0])); + grad_edge = grad_edge / edgeLength; + + // set local maximum over all gradients along the edge to a given vertex + DoFRef(grad, vInd1[0]) = std::max(DoFRef(grad, vInd1[0]), + grad_edge); + DoFRef(grad, vInd2[0]) = std::max(DoFRef(grad, vInd2[0]), + grad_edge); + + } // end edge-loop + + } + + } // end elem-loop + +} + +template +void MovingParticle::adjust_global_solution(vector_type& u, + const int topLevel) { + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + + for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + +#ifdef UG_PARALLEL + std::vector ElemList = + m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + UG_LOG( + "1 MovingParticle::copy_and_fill_solution: ElemList.size(): " << ElemList.size() << "\n"); + if (ElemList.size() == 0) { + UG_LOG( + "2 MovingParticle::copy_and_fill_solution: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + continue; + } +#endif + + // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) + std::vector < DoFIndex > transInd = + m_spParticleHandlerGlobal->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd( + levIndex, p); + + MathVector transSol = m_spParticleHandlerGlobal->get_transSol(p, + 0); + MathVector rotSol = m_spParticleHandlerGlobal->get_rotSol(p, 0); + + UG_LOG( + "in adjust_global_solution(): transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); + UG_LOG( + "in adjust_global_solution(): transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); + UG_LOG( + "in adjust_global_solution(): rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); + UG_LOG( + "in adjust_global_solution (): rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); + + ConstSmartPtr dd = + this->m_spApproxSpace->dof_distribution( + GridLevel(topLevel, GridLevel::LEVEL)); + typename TDomain::position_accessor_type aaPos = + m_spParticleHandlerGlobal->m_aaPos; + + const MathVector& center = m_spParticleHandlerGlobal->get_center( + p); + + typedef typename std::vector::iterator ListIter; + + // loop all elements relevant for prtIndex-th particle + std::vector ElemListLog = + m_spParticleHandlerGlobal->m_vvvElemListOutside[levIndex][p]; + + for (ListIter listIter = ElemListLog.begin(); + listIter != ElemListLog.end(); ++listIter) { + // get element + grid_base_object* elem = *listIter; + + // collect all vertices of the element + std::vector vVertex; + CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + + // loop vertices + for (size_t v = 0; v < vVertex.size(); ++v) { + // get vertex + Vertex* vrt = vVertex[v]; + + for (size_t fct = 0; fct < dim; ++fct) { + // create multi index + std::vector < DoFIndex > vInd; + // get multi indices + if (dd->inner_dof_indices(vrt, fct, vInd) != 1) + UG_THROW("Only one index expected."); + + // set solution: particle velocity + MathVector radialCo; + VecSubtract(radialCo, aaPos[vrt], center); + MathMatrix rotationMatCo = + m_spParticleHandlerGlobal->get_rotationMat( + radialCo); + + // set solution + DoFRef(u, vInd[0]) = transSol[fct]; + for (int d = 0; d < dim; ++d) + DoFRef(u, vInd[0]) += rotationMatCo[fct][d] * rotSol[d]; + + DoFRef(u, vInd[0]) = 0.0; + + } + + } // end vrt-loop + } // end outsideElem-loop + + } // end prt-loop + +} + +template +void MovingParticle::fill_particle_solution(vector_type& u, + const int topLevel, const number time) { + + bool output = false; + + const char* filename = "freed_solution"; + std::string name(filename); + char ext[50]; + sprintf(ext, ".txt"); + name.append(ext); + FILE* outputFile = fopen(name.c_str(), "a"); + if (output) { + fprintf(outputFile, + "------------------------------------------------------------- \n"); + fprintf(outputFile, "-- 'fill_particle_solution()' for time = %e -- \n", + time); + fprintf(outputFile, + "------------------------------------------------------------- \n"); + } + + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + + for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + +#ifdef UG_PARALLEL + std::vector ElemList = + m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + UG_LOG( + "1 MovingParticle::copy_and_fill_solution: ElemList.size(): " << ElemList.size() << "\n"); + if (ElemList.size() == 0) { + UG_LOG( + "2 MovingParticle::copy_and_fill_solution: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + continue; + } +#endif + + // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) + std::vector < DoFIndex > transInd = + m_spParticleHandlerGlobal->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd( + levIndex, p); + + MathVector transSol = m_spParticleHandlerGlobal->get_transSol(p,0); + MathVector rotSol = m_spParticleHandlerGlobal->get_rotSol(p, 0); + + UG_LOG( + "in fill_particle_solution(): transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); + UG_LOG( + "in fill_particle_solution(): transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); + UG_LOG( + "in fill_particle_solution(): rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); + UG_LOG( + "in fill_particle_solution(): rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); + + ConstSmartPtr dd = + this->m_spApproxSpace->dof_distribution( + GridLevel(topLevel, GridLevel::LEVEL)); + typename TDomain::position_accessor_type aaPos = + m_spParticleHandlerGlobal->m_aaPos; + + const MathVector& center = m_spParticleHandlerGlobal->get_center( + p); + + typedef typename std::vector::iterator ListIter; + + // loop all elements relevant for prtIndex-th particle + std::vector ElemListLog = + m_spParticleHandlerGlobal->m_vvvElemListOutside[levIndex][p]; + + /* for(ListIter listIter = ElemListLog.begin(); + listIter != ElemListLog.end(); ++listIter) + { + // get element + grid_base_object* elem = *listIter; + + // collect all vertices of the element + std::vector vVertex; + CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + + // loop vertices + for(size_t v = 0; v < vVertex.size(); ++v) + { + // get vertex + Vertex* vrt = vVertex[v]; + + + for (size_t fct = 0; fct < dim; ++fct) + { + // create multi index + std::vector vInd; + // get multi indices + if(dd->inner_dof_indices(vrt, fct, vInd) != 1) + UG_THROW("Only one index expected."); + + // set solution: particle velocity + MathVector radialCo; + VecSubtract(radialCo, aaPos[vrt], center); + MathMatrix rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(radialCo); + + // set solution + DoFRef(u,vInd[0]) = transSol[fct]; + for ( int d = 0; d < dim; ++d ) + DoFRef(u,vInd[0]) += rotationMatCo[fct][d]*rotSol[d]; + + } + + + } // end vrt-loop + } // end outsideElem-loop + */ + // loop all elements relevant for prtIndex-th particle + ElemListLog = m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + + for (ListIter listIter = ElemListLog.begin(); + listIter != ElemListLog.end(); ++listIter) { + // get element + grid_base_object* elem = *listIter; + + // collect all vertices of the element + std::vector vVertex; + CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + + // loop vertices + for (size_t v = 0; v < vVertex.size(); ++v) { + // get vertex + Vertex* vrt = vVertex[v]; + + // ---> is_outsideFluid() is a geometrical check w.r.t new particle coords + // ---> m_spOutsideMarker was marked w.r.t old particle coords + // ===> !is_inside && is_outside = is_freed :-) + if (m_spParticleHandlerGlobal->is_outsideFluid_prtIndex(p, vrt) + && m_spParticleHandlerGlobal->m_spOutsideMarker->is_marked( + vrt)) { + if (1) { + fprintf(outputFile, " freed node: %e \t %e \t", + aaPos[vrt][0], aaPos[vrt][1]); + if (dim == 3) + fprintf(outputFile, " node: %e", aaPos[vrt][2]); + fprintf(outputFile, " time: %e \n\n", time); + } + + for (size_t fct = 0; fct < dim; ++fct) { + // create multi index + std::vector < DoFIndex > vInd; + // get multi indices + if (dd->inner_dof_indices(vrt, fct, vInd) != 1) + UG_THROW("Only one index expected."); + + // set solution: particle velocity + MathVector radialCo; + VecSubtract(radialCo, aaPos[vrt], center); + MathMatrix rotationMatCo = + m_spParticleHandlerGlobal->get_rotationMat( + radialCo); + + if (output) + { + fprintf(outputFile, "fct = %lu:\n", fct); + fprintf(outputFile," transSol: %e, \t rotSol: %e\n", transSol[fct], rotSol[fct]); + fprintf(outputFile, " vorher: %e, \t", DoFRef(u, vInd[0])); + } + // set solution + DoFRef(u, vInd[0]) = transSol[fct]; + + if ( output) + { + UG_LOG(" fill_sol_: transInd(0) = " << transInd[0] << "\n"); + UG_LOG(" fill_sol_: rotInd(0) = " << rotInd[0] << "\n"); + UG_LOG(" fill_sol_: transSol[" << fct << "]: " << transSol[fct] << "\n"); + UG_LOG(" fill_sol_: rotSol[" << fct << "]: " << rotSol[fct] << "\n"); + } + + for (int d = 0; d < dim; ++d) + DoFRef(u, vInd[0]) += rotationMatCo[fct][d] + * rotSol[d]; + + if (output) + fprintf(outputFile, " nachher: %e \n\n", + DoFRef(u, vInd[0])); + + } + // wenn node ganz im Inneren vom Partikel liegt (!FlatTopVrtMarker), dann hat sich das Partikel zu schnell + // weiterbewegt -> CFL-Schranke verletzt! + if (!m_spParticleHandlerGlobal->m_spFlatTopVrtMarker->is_marked( + vrt) + && m_spParticleHandlerGlobal->m_spOutsideMarker->is_marked( + vrt)) + UG_THROW( + "in 'fill_particle_solution()': CFL-Schranke verletzt!\n"); + } + + } // end vrt-loop + } // end cutElem-loop + + } // end prt-loop + + fclose(outputFile); + +} + +template +void MovingParticle::clear_solution(vector_type& u, + const int topLevel) { +// const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + +} + +// call via lua BEFORE applying 'movingParticle:update()', which changes the global indices of trandSol/rotSol +// necessary for re-writing solution to NEW indices of vector 'u' during 'update_solution' +// => handling instance/buffering data := m_spParticleHandlerGlobal->(m_vSolTrans/m_vSolRot) + +// transfer direction: m_vSolTrans ---> DoFRef(u, transInd) +template +void MovingParticle::update_particle_solution(vector_type& u, const int topLevel) +{ + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + + for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + +#ifdef UG_PARALLEL + std::vector ElemList = + m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + UG_LOG( + "1 MovingParticle::update_solution: ElemList.size(): " << ElemList.size() << "\n"); + if (ElemList.size() == 0) { + UG_LOG( + "2 MovingParticle::update_solution: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + continue; + } +#endif + + // 'get_transInd()' returns allready updated indices (updated during 'movingParticle:update()' vie lua) + std::vector < DoFIndex > transInd = m_spParticleHandlerGlobal->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd(levIndex, p); + + UG_LOG("in 'update_particle_solution()': transInd = " << transInd[0] << "\n"); + UG_LOG("in 'update_particle_solution()': rotInd = " << rotInd[0] << "\n"); + + for (int d = 0; d < dim; ++d) { +#ifdef UG_DEBUG + UG_LOG( + "VORHER: in 'update_solution()': DoFRef(u, transInd[d]) = " << DoFRef(u, transInd[d]) << "\n"); + UG_LOG( + "VORHER: in 'update_solution()': DoFRef(u, rotInd[d]) = " << DoFRef(u, rotInd[d]) << "\n"); +#endif + DoFRef(u, transInd[d]) = m_spParticleHandlerGlobal->get_transSol(p,0)[d]; + DoFRef(u, rotInd[d]) = m_spParticleHandlerGlobal->get_rotSol(p, 0)[d]; +#ifdef UG_DEBUG + UG_LOG( + "NACHHER: in 'update_solution()': DoFRef(u, transInd[d]) = " << DoFRef(u, transInd[d]) << "\n"); + UG_LOG( + "NACHHER: in 'update_solution()': DoFRef(u, rotInd[d]) = " << DoFRef(u, rotInd[d]) << "\n"); +#endif + } + + } // end particle loop + +} + + + template + bool MovingParticle::mark_collision_area(SmartPtr refiner, int level) + { + + //typedef typename TDomain::position_accessor_type position_accessor_type; + typedef typename GeomObjBaseTypeByDim::base_obj_type elem_t; + //typedef typename ElementStorage::SectionContainer::iterator BaseElemIterator; + //typedef typename elem_t::side side_t; + //typedef typename std::vector::iterator ElemIterator; + typedef typename std::map::iterator ElemMapIterator; + + typedef typename geometry_traits::iterator ElemIterator; + + bool elem_is_cut_by_2 = false; + + std::map num_cuts; + + // access the grid and the position attachment + MultiGrid* mg = (refiner->multi_grid()); + //position_accessor_type& aaPos = dom.position_accessor(); + + for (ElemIterator elemIter = mg->begin(); elemIter != mg->end(); ++elemIter) { + elem_t* elem = *elemIter; + for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + //std::vector ElemListLog = m_vvvElemListCut[level][p]; + //for (ElemIterator elem = ElemListLog.begin(); + //elem != ElemListLog.end(); ++elem) { + bool cut = false; + for (size_t v = 0; v < elem->num_vertices(); ++v) { + const MathVector& vrtPos = m_spParticleHandlerGlobal->m_aaPos[elem->vertex(v)]; + const MathVector& center = m_spParticleHandlerGlobal->get_center(p); + const number radius = m_spParticleHandlerGlobal->get_radius(p); + + if (VecDistance(vrtPos, center) <= radius) { + cut = true; + } + } + if (cut) { + num_cuts[elem]++; + } + } + } + for (ElemMapIterator cut_elem = num_cuts.begin(); cut_elem != num_cuts.end(); ++cut_elem) { + if (cut_elem->second >= 2 && !mg->has_children(cut_elem->first)) { + refiner->mark(cut_elem->first); + elem_is_cut_by_2 = true; + } + } + return elem_is_cut_by_2; + } + + template + double MovingParticle::estimate_repulsive_force_parameters(vector_type& u, int topLevel, double maxElemDiameter, double deltaT){ + // Get and synchronize velocities + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + + std::vector > transVel; + int num_particles = m_spParticleHandlerGlobal->num_particles(); + transVel.resize(num_particles); + + bool verbose = false; + MathVector transVelP; + +#ifdef UG_PARALLEL + pcl::ProcessCommunicator com; + + for (size_t p = 0; p < num_particles; ++p) { + + std::vector ElemList = + m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + if (ElemList.size() == 0) { + for (int d = 0; d < dim; ++d) { + transVelP[d] = 0.0; + } + } else { + std::vector < DoFIndex > transInd = + m_spParticleHandlerGlobal->get_transInd(levIndex, p); + + for (int d = 0; d < dim; ++d) { + transVelP[d] = DoFRef(u, transInd[d]); + } + + } + if (verbose) { + UG_LOG(pcl::ProcRank()<< "sends (" << transVelP[0] << "," << transVelP[1] << ")\n"); + } + com.allreduce(&transVelP[0],&transVel[p][0], dim, MPI_DOUBLE, PCL_RO_SUM); + if (verbose) { + if (dim == 1) { + UG_LOG("transVel[p] = ("<< transVel[p][0] <<")\n"); + } else{ + if (dim == 2) { + UG_LOG("transVel[p] = ("<< transVel[p][0] << "," << transVel[p][1] <<")\n"); + } else { + if (dim == 3) { + UG_LOG("transVel[p] = ("<< transVel[p][0] << "," << transVel[p][1] << "," << transVel[p][2] <<")\n"); + } + } + } + } + } +#else + for (size_t p = 0; p < num_particles; ++p) { + std::vector < DoFIndex > transInd = + m_spParticleHandlerGlobal->get_transInd(levIndex, p); + + for (int d = 0; d < dim; ++d) { + transVelP[d] = DoFRef(u, transInd[d]); + } + } +#endif + + double eps = 0.0; + //const int levIndex = get_Index(GridLevel(13957 /*topLevel*/, GridLevel::LEVEL)); + + for (size_t p = 0; p < num_particles; ++p){ + // Get values for particle p + MathVector center_p = m_spParticleHandlerGlobal->get_center(p); + VecScaleAdd(center_p, 1.0, center_p, deltaT, transVel[p]); + number radius_p = m_spParticleHandlerGlobal->get_radius(p); + //double Mass_p = m_spInterfaceMapper->Mass(13957,p); + for (size_t q = 0; q < num_particles; ++q){ + if (p == q) { + continue; + } + if (verbose) + UG_LOG("p = "< center_q = m_spParticleHandlerGlobal->get_center(q); + VecScaleAdd(center_q, 1.0, center_q, deltaT, transVel[q]); + number radius_q = m_spParticleHandlerGlobal->get_radius(q); + //double Mass_q = m_spInterfaceMapper->Mass(13957,q); + // Calculate force + if (verbose) { + if (dim == 1) { + UG_LOG("center_p = ("<< center_p[0] <<")\n"); + } else{ + if (dim == 2) { + UG_LOG("center_p = ("<< center_p[0] << "," << center_p[1] <<")\n"); + } else { + if (dim == 3) { + UG_LOG("center_p = ("<< center_p[0] << "," << center_p[1] << "," << center_p[2] <<")\n"); + } + } + } + if (dim == 1) { + UG_LOG("center_q = ("<< center_q[0] <<")\n"); + } else{ + if (dim == 2) { + UG_LOG("center_q = ("<< center_q[0] << "," << center_q[1] <<")\n"); + } else { + if (dim == 3) { + UG_LOG("center_q = ("<< center_q[0] << "," << center_q[1] << "," << center_q[2] <<")\n"); + } + } + } + } + number centerDist = VecDistance(center_q, center_p); + if (verbose) + UG_LOG("centerDist = "<< centerDist <<"\n"); + number s_ij = centerDist - radius_p - radius_q; + if (verbose) + UG_LOG("centerDist - radius_p - radius_q = "<< s_ij <<"\n"); + number dist = maxElemDiameter - s_ij; + if (verbose) + UG_LOG("maxElemDiameter - s_ij = " << dist <<"\n"); + eps = std::max(eps,dist); + } + } + return eps; + } + + +} // end namespace NavierStokes +} // end namespace ug + +#endif /* MOVING_PARTICLE_IMPL_H_ */ diff --git a/incompressible/fv1/moving_particle/moving_particle_tools.h b/incompressible/fv1/moving_particle/moving_particle_tools.h new file mode 100644 index 0000000..5f81590 --- /dev/null +++ b/incompressible/fv1/moving_particle/moving_particle_tools.h @@ -0,0 +1,502 @@ +/* + * moving_particle_tools.h + * + * Created on: 20.01.2015 + * Author: suze + */ + +#ifndef MOVING_PARTICLE_TOOLS_H_ +#define MOVING_PARTICLE_TOOLS_H_ + +namespace ug{ +namespace NavierStokes{ + + +template +void MovingParticle:: +interpolate_point(ConstSmartPtr dd, + const vector_type& u, + const MathVector& evalPos, // input data + MathVector& interpolation) // output data +{ + MathVector localPos(0.0); + +// get data + typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); + + // create Function Group + FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); + + // get iterators for all elems on subset + typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; + + typename DoFDistribution::traits::const_iterator iter, iterEnd; + iter = dd->begin(); + iterEnd = dd->end(); + + + // loop elements in order to compute 'U_global' and 'omega_global': + for( ; iter != iterEnd; ++iter) + { + // get element + grid_base_object* elem = *iter; + + if ( ContainsPoint(elem, evalPos, aaPos) ) + { + // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...) + ReferenceObjectID roid = (ReferenceObjectID) elem->reference_object_id(); + + // get all corner coordinates + std::vector > vCorner; + CollectCornerCoordinates(vCorner, *elem, aaPos, true); + + // get the reference mapping for the element using global corners + DimReferenceMapping& mapping + = ReferenceMappingProvider::get(roid, vCorner); + + + // compute global integration points + mapping.global_to_local(localPos, evalPos); + + // loop all velocity components + for(int cmp = 0; cmp < dim+1; ++cmp) + { + // get fct id for compent + const size_t fct = fctGrp[cmp]; + + // local finite element id + const LFEID m_id = dd->local_finite_element_id(fct); + + // get trial space + const LocalShapeFunctionSet& rTrialSpace = + LocalFiniteElementProvider::get(roid, m_id); + + // number of dofs on element + const size_t num_sh = rTrialSpace.num_sh(); + + // get multiindices of element + std::vector ind; // aux. index array + dd->dof_indices(elem, fct, ind); + + // check multi indices + if(ind.size() != num_sh) + UG_THROW("L2ErrorIntegrand::evaluate: Wrong number of" + " multi indices."); + + // compute approximated solution at integration point + interpolation[cmp] = 0.0; + for(size_t sh = 0; sh < num_sh; ++sh) + { + // get value at shape point (e.g. corner for P1 fct) + const number valSH = DoFRef(u, ind[sh]); + //UG_LOG("interpolate: valSh = " << valSH << "\n"); + // add shape fct at ip * value at shape + interpolation[cmp] += valSH * rTrialSpace.shape(sh, localPos); + //UG_LOG("interpolate: interpolation[" << cmp << "] = " << interpolation[cmp] << "\n"); + + } + + } // end cmp-loop + + } // end if-ContainsPoint + + + } // end element-loop + + //UG_LOG("end: interpolation = " << interpolation[dim] << "\n"); + } + + +template +void MovingParticle:: +print_pressure_nodal(const vector_type& u, const int topLevel) +{ + UG_LOG("START print_pressure_nodal()\n"); + + FILE *pressure; + char filename1[40]; + sprintf(filename1, "pressure_nodal_teta_level%d.txt", topLevel); + pressure = fopen(filename1, "w"); + FILE *pressure_on_interface; + char filename2[40]; + sprintf(filename2, "pressure_nodal_teta_level_ON_interface%d.txt", topLevel); + pressure_on_interface = fopen(filename2, "w"); + int numIter = 0; + number dist = 0.0; + + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + std::vector ElemListLog = m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][0]; + ConstSmartPtr dd = this->m_spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + typename TDomain::position_accessor_type aaPos = m_spParticleHandlerGlobal->m_aaPos; + + const MathVector& center = m_spParticleHandlerGlobal->get_center(0); + + UG_LOG("center " << center << "\n"); + + typedef typename std::vector::iterator ListIter; + + // loop all elements relevant for prtIndex-th particle + for(ListIter listIter = ElemListLog.begin(); + listIter != ElemListLog.end(); ++listIter) + { + numIter++; + // get element + grid_base_object* elem = *listIter; + + // collect all vertices of the element + std::vector vVertex; + CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + + MathVector bufferVector; + VecSubtract(bufferVector, aaPos[vVertex[0]], aaPos[vVertex[2]]); + dist = 0.5*VecLength(bufferVector); + + // loop vertices + for(size_t v = 0; v < vVertex.size(); ++v) + { + // get vertex + Vertex* vrt = vVertex[v]; + + if ( !m_spParticleHandlerGlobal->is_outsideFluid(vrt) ) + { + std::vector vInd; + if(dd->inner_dof_indices(vrt, dim, vInd) != 1) + UG_THROW("Only one index expected."); + + MathVector radialVector; + radialVector[0] = aaPos[vrt][0]-center[0]; + radialVector[1] = aaPos[vrt][1]-center[1]; + + number teta = atan2(aaPos[vrt][1]-center[1], aaPos[vrt][0]-center[0]); + if ( teta < 0.0 ) + teta += 2*3.1415926; + + fprintf(pressure, "%e \t %e \t %lu # teta, value pressure, KnotenIndex vInd[0] \n", teta, DoFRef(u, vInd[0]), vInd[0][0]); + + } + if ( m_spParticleHandlerGlobal->is_outsideFluid(vrt) ) + { + std::vector vInd; + if(dd->inner_dof_indices(vrt, dim, vInd) != 1) + UG_THROW("Only one index expected."); + + MathVector radialVector; + radialVector[0] = aaPos[vrt][0]-center[0]; + radialVector[1] = aaPos[vrt][1]-center[1]; + + number teta = atan2(aaPos[vrt][1]-center[1], aaPos[vrt][0]-center[0]); + if ( teta < 0.0 ) + teta += 2*3.1415926; + + fprintf(pressure_on_interface, "%e \t %e \t %lu # teta, value pressure, KnotenIndex vInd[0] \n", teta, DoFRef(u, vInd[0]), vInd[0][0]); + + } + } + + } + + + fclose(pressure); + fclose(pressure_on_interface); + + UG_LOG("print_pressure_nodal() done...\n"); +} + +template +void MovingParticle:: +print_deltaP(const vector_type& u, const int topLevel) +{ + UG_LOG("START print_pressure()\n"); + + FILE *pressure; + char filename1[40]; + sprintf(filename1, "delta_pressure_level%d.txt", topLevel); + pressure = fopen(filename1, "w"); + + ConstSmartPtr dd = this->m_spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + MathVector printPos1; + MathVector printPos2; + printPos1[0] = 0.15; + printPos1[1] = 0.2; + printPos2[0] = 0.25; + printPos2[1] = 0.2; + + MathVector interpolVal1; + MathVector interpolVal2; + + interpolate_point(dd, u, printPos1, interpolVal1); + interpolate_point(dd, u, printPos2, interpolVal2); + + number deltaP = interpolVal1[dim] - interpolVal2[dim]; + + UG_LOG("interpolVal1[" << dim<< "] = " << interpolVal1[dim] << "\n"); + UG_LOG("interpolVal2[" << dim<< "] = " << interpolVal2[dim] << "\n"); + UG_LOG("deltaP = " << deltaP << "\n"); + + fprintf(pressure, "%e \t %e \t %e \n# interpolVal1[dim], interpolVal1[dim], deltaP\n", interpolVal1[dim], interpolVal2[dim], deltaP); + fclose(pressure); + +} + +template +void MovingParticle:: +print_pressure(const vector_type& u, const int topLevel) +{ + UG_LOG("START print_pressure()\n"); + + FILE *pressure; + char filename1[40]; + sprintf(filename1, "pressure_MovPrtSTdFV_teta_level%d.txt", topLevel); + pressure = fopen(filename1, "w"); + + ConstSmartPtr dd = this->m_spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + const MathVector& center = m_spParticleHandlerGlobal->get_center(0); + + size_t t_max = 500; + MathVector printPos; + MathVector interpolVal; + for(size_t t = 0; t < t_max; ++t) + { + number teta = t*(2*PI/t_max); + number co = cos(teta); + number si = sin(teta); + printPos[0] = 0.2*co + center[0]; + printPos[1] = 0.2*si + center[1]; + interpolate_point(dd, u, printPos, interpolVal); + + //UG_LOG("after: interpolVal[" << dim<< "] = " << interpolVal[dim] << "\n"); + fprintf(pressure, "%e \t", teta); + fprintf(pressure, "%e \t", interpolVal[dim]); + fprintf(pressure, "%e \t %e # teta, value_pressure, printPos[0], printPot[1]\n", printPos[0], printPos[1]); + } + + fclose(pressure); + + //UG_THROW("Vorsicht bei Enwednugn von 'print_pressure()': früher wurde der Vektor 'interpolVal' an der Stelle dim+1 statt dim ausgelesen!!\n"); +} + + /* +template +void MovingParticle:: +compute_error_on_circle(const vector_type& u, const int topLevel, number r) +{ + FILE *solution; + char filename1[40]; + sprintf(filename1, "error_MovPrt_radius%e_level%d.txt", r, topLevel); + solution = fopen(filename1, "w"); + + const MathVector& center = m_spParticleHandlerGlobal->get_center(0); + const number R = m_spParticleHandlerGlobal->get_radius(0); + ConstSmartPtr dd = this->m_spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + number error_u = 0.0; + number error_v = 0.0; + number error_p = 0.0; + + size_t t_max = 500; + MathVector printPos; + MathVector interpolVal; + for(size_t t = 0; t < t_max; ++t) + { + number teta = t*(2*PI/t_max); + number co = cos(teta); + number si = sin(teta); + printPos[0] = r*co + center[0]; + printPos[1] = r*si + center[1]; + interpolate_point(dd, u, printPos, interpolVal); + + number sol_u = ((R*R-r*r)*co*co + r*r*log(r/R) + 0.5*(r*r-R*R))/(r*r); + number sol_v = ((R*R-r*r)*si*co)/(r*r); + number sol_p = -2*co*r; + + error_u += fabs(interpolVal[0]-sol_u); + error_v += fabs(interpolVal[1]-sol_v); + error_p += fabs(interpolVal[2]-sol_p); + + fprintf(solution, "%e \t", teta); + for ( size_t i = 0; i <= dim; ++i) + fprintf(solution, "%e \t", interpolVal[i]); + + fprintf(solution, "%e \t %e # teta, interpolVal[0], interpolVal[1], interpolVal[2], printPos[0], printPot[1]\n", printPos[0], printPos[1]); + + } + + fclose(solution); + + UG_LOG("error_u: " << error_u/500 << "\n"); + UG_LOG("error_v: " << error_v/500 << "\n"); + UG_LOG("error_p: " << error_p/500 << "\n\n"); + +} +*/ +template +void MovingParticle:: +print_velocity(const vector_type& u, const int topLevel, number time, const char* filename) +{ + UG_LOG("MovingParticle::print_velocity(): Start: \n"); + + // Parameter von class 'MovingParticle' extrahieren: + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + const bool isTimedep = is_time_dependent(); + + size_t numPrt = m_spParticleHandlerGlobal->num_particles(); + +// if ( numPrt > 2 ) +// UG_THROW("Particle:output_velocity: VORSICHT, output nicht implementiert fuer mehr als 2 particle! -> m_bShared[][] ist Problem! ... Exit! \n"); + + for(size_t p = 0; p < numPrt; ++p) + { + +#ifdef UG_PARALLEL + std::vector ElemList = m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + UG_LOG("1 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << "\n"); + if (ElemList.size() == 0) { + UG_LOG("2 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + continue; + } +#endif + + // Parameter von class 'CutElementHandler' extrahieren: + + // get multiindices for translation and rotation of particle + std::vector < DoFIndex > transInd = m_spParticleHandlerGlobal->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd(levIndex, p); + + MathVector transSol; + MathVector rotSol; + + for ( int d = 0; d < dim; ++d ) + { + transSol[d] = DoFRef(u, transInd[d]); + rotSol[d] = DoFRef(u, rotInd[d]); + } + + // auf untergeordnete class 'ParticleProvider' weiterleiten: + m_spParticleHandlerGlobal->print_velocity(transSol, rotSol, p, isTimedep, time, filename); + } + + UG_LOG("output_velocity....DONE\n"); + +} + /* + +template +void MovingParticle:: +print_velocity_many_particles(const vector_type& u, const int topLevel, number time, const char* filename) +{ + UG_LOG("MovingParticle::print_velocity(): Start: \n"); + + size_t numPrt = m_spParticleHandlerGlobal->num_particles(); + + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + number distance = -10.0; + + // compute distance between 2 particles + if ( numPrt == 2 ) + { + const number radius1 = m_spParticleHandlerGlobal->get_radius(0); + const number radius2 = m_spParticleHandlerGlobal->get_radius(1); + + const number radius = radius1+radius2; + + MathVector distVec; + VecSubtract(distVec, m_spParticleHandlerGlobal->get_center(1), m_spParticleHandlerGlobal->get_center(0)); + + distance = VecDot(distVec, distVec); + distance = sqrt(distance); + distance = distance - radius; + } + for(size_t p = 0; p < numPrt; ++p) + { + +#ifdef UG_PARALLEL + std::vector ElemList = m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + UG_LOG("1 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << "\n"); + if (ElemList.size() == 0) { + UG_LOG("2 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + continue; + } +#endif + // get multiindices for translation and rotation of particle + std::vector < DoFIndex > transInd = m_spParticleHandlerGlobal->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd(levIndex, p); + + MathVector transSol; + MathVector rotSol; + + MathVector center = m_spParticleHandlerGlobal->get_center(p); + const number radius = m_spParticleHandlerGlobal->get_radius(p); + + for ( int d = 0; d < dim; ++d ) + { + transSol[d] = DoFRef(u, transInd[d]); + rotSol[d] = DoFRef(u, rotInd[d]); + } + + number f1 = 0.0; + number gravity = -9.81; + if ( !is_time_dependent() ) + f1 = transSol[0]*4.0/(radius*radius*gravity); + + std::string name(filename); + + char * cstr = new char [name.size()+1]; + strcpy (cstr, name.c_str()); + + + if ( !is_time_dependent() ) + { + FILE* print_velocity = fopen(name.c_str(), "a"); + + + fprintf(print_velocity,"%e \t %e \t ",radius, f1); + for ( int d = 0; d < dim; ++d ) + fprintf(print_velocity,"%e \t %e \t ", transSol[d], rotSol[d]); + for ( int d = 0; d < dim; ++d ) + fprintf(print_velocity,"%e \t ", center[d]); + + fprintf(print_velocity," # radius, f1, transVel[0], rotVel[0], transVel[1], rotVel[1], center_coords, (m_bSharedIP = "); + fprintf(print_velocity, "0 ), "); + + fprintf(print_velocity," (m_bSharedElem = "); + fprintf(print_velocity, "0 ) \n "); + fclose(print_velocity); + + } + else + { + FILE* print_velocity = fopen(name.c_str(), "a"); + + fprintf(print_velocity,"%e \t ",time); + + for ( int d = 0; d < dim; ++d ) + fprintf(print_velocity,"%e \t %e \t ", transSol[d], rotSol[d]); + + for ( int d = 0; d < dim; ++d ) + fprintf(print_velocity,"%e \t ", center[d]); + + + fprintf(print_velocity,"%e \t ", distance); + + fprintf(print_velocity," # time, transVel[0], rotVel[0], transVel[1], rotVel[1], center_coords, (m_bSharedIP = "); + fprintf(print_velocity, "0 ), "); + + fprintf(print_velocity," (m_bSharedElem = "); + fprintf(print_velocity, "0 ) \n "); + fclose(print_velocity); + + } + + } + + UG_LOG("output_velocity....DONE\n"); + +} +*/ +} // end namespace NavierStokes +} // end namespace ug + + + +#endif /* MOVING_PARTICLE_TOOLS_H_ */ diff --git a/incompressible/fv1/navier_stokes_fv1.cpp b/incompressible/fv1/navier_stokes_fv1.cpp index f93307e..b770221 100644 --- a/incompressible/fv1/navier_stokes_fv1.cpp +++ b/incompressible/fv1/navier_stokes_fv1.cpp @@ -32,10 +32,12 @@ #include "navier_stokes_fv1.h" -#include "lib_disc/spatial_disc/disc_util/fv1_geom.h" +#include "lib_disc/spatial_disc/disc_util/fv1FT_geom.h" #include "lib_disc/spatial_disc/disc_util/geom_provider.h" namespace ug{ + + namespace NavierStokes{ //////////////////////////////////////////////////////////////////////////////// @@ -102,6 +104,8 @@ prepare_setting(const std::vector& vLfeID, bool bNonRegularGrid) UG_THROW("NavierStokes: 'fv1' expects Lagrange P1 trial space " "for velocity and pressure."); + m_LFEID = vLfeID[0]; + // update assemble functions register_all_funcs(false); } @@ -146,16 +150,16 @@ prep_elem_loop(const ReferenceObjectID roid, const int si) // check, that stabilization has been set if(m_spStab.invalid()) UG_THROW("Stabilization has not been set."); - + // init stabilization for element type m_spStab->template set_geometry_type(); - + if (! m_bStokes) // no convective terms in the Stokes eq. => no upwinding { // check, that convective upwinding has been set if(m_spConvStab.invalid() && m_spConvUpwind.invalid()) UG_THROW("Upwinding for convective Term in Momentum eq. not set."); - + // init convection stabilization for element type if(m_spConvStab.valid()) m_spConvStab->template set_geometry_type(); @@ -179,12 +183,13 @@ prep_elem_loop(const ReferenceObjectID roid, const int si) if(!m_imDensitySCV.data_given()) UG_THROW("NavierStokes::prep_elem_loop:" " Density has not been set, but is required."); - + // set local positions for imports - if(!TFVGeom::usesHangingNodes) + //if(!TFVGeom::usesHangingNodes) + if(!TFVGeom::usesHangingNodes && TFVGeom::staticLocalData) { static const int refDim = TElem::dim; - TFVGeom& geo = GeomProvider::get(); + TFVGeom& geo = GeomProvider::get(m_LFEID, 1); const MathVector* vSCVFip = geo.scvf_local_ips(); const size_t numSCVFip = geo.num_scvf_ips(); const MathVector* vSCVip = geo.scv_local_ips(); @@ -195,7 +200,7 @@ prep_elem_loop(const ReferenceObjectID roid, const int si) m_imSourceSCV.template set_local_ips(vSCVip,numSCVip); m_imSourceSCVF.template set_local_ips(vSCVFip,numSCVFip); } - + } template @@ -211,15 +216,16 @@ void NavierStokesFV1:: prep_elem(const LocalVector& u, GridObject* elem, ReferenceObjectID roid, const MathVector vCornerCoords[]) { // Update Geometry for this element - TFVGeom& geo = GeomProvider::get(); - try{ + TFVGeom& geo = GeomProvider::get(m_LFEID, 1); + try{ geo.update(elem, vCornerCoords, &(this->subset_handler())); } UG_CATCH_THROW("NavierStokes::prep_elem:" " Cannot update Finite Volume Geometry."); // set local positions for imports - if(TFVGeom::usesHangingNodes) + //if(TFVGeom::usesHangingNodes) + if(TFVGeom::usesHangingNodes || !TFVGeom::staticLocalData) { // request ip series static const int refDim = TElem::dim; @@ -250,13 +256,14 @@ prep_elem(const LocalVector& u, GridObject* elem, ReferenceObjectID roid, const template template void NavierStokesFV1:: -add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) +add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, + const MathVector vCornerCoords[]) { // Only first order implementation UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // check for source term to pass to the stabilization const DataImport, dim>* pSource = NULL; @@ -280,7 +287,9 @@ add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat } // interpolate velocity at ip with standard lagrange interpolation - static const size_t numSCVF = TFVGeom::numSCVF; + //static const size_t numSCVF = TFVGeom::numSCVF; + static const size_t numSCVF = TFVGeom::maxNumSCVF; + MathVector StdVel[numSCVF]; for(size_t ip = 0; ip < geo.num_scvf(); ++ip) { @@ -605,7 +614,7 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // check for source term to pass to the stabilization const DataImport, dim>* pSource = NULL; @@ -629,7 +638,9 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat } // interpolate velocity at ip with standard lagrange interpolation - static const size_t numSCVF = TFVGeom::numSCVF; + //static const size_t numSCVF = TFVGeom::numSCVF; + static const size_t numSCVF = TFVGeom::maxNumSCVF; + MathVector StdVel[numSCVF]; for(size_t ip = 0; ip < geo.num_scvf(); ++ip) { @@ -775,6 +786,7 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat d(_P_, scvf.from()) += contFlux; d(_P_, scvf.to() ) -= contFlux; } + } @@ -787,7 +799,7 @@ add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) @@ -817,7 +829,7 @@ add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) @@ -850,7 +862,7 @@ add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoor if(!m_imSourceSCV.data_given()) return; // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) @@ -907,7 +919,7 @@ ex_velocity_grad(MathMatrix vValue[], std::vector > > vvvDeriv[]) { // Get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // reference element typedef typename reference_element_traits::reference_element_type ref_elem_type; @@ -1011,7 +1023,10 @@ register_all_funcs(bool bHang) // switch assemble functions if(!bHang) { - register_func >(); + + // register_func >(); + + register_func > >(); } else { @@ -1028,14 +1043,20 @@ register_all_funcs(bool bHang) // switch assemble functions if(!bHang) { - register_func >(); - register_func >(); + + // register_func >(); + // register_func >(); + + register_func > >(); + // register_func > >(); } else { UG_THROW("NavierStokesFV1: Hanging Nodes not implemented.") } + } + #endif #ifdef UG_DIM_3 @@ -1046,11 +1067,15 @@ register_all_funcs(bool bHang) // switch assemble functions if(!bHang) { - register_func >(); - register_func >(); - register_func >(); - register_func >(); - } + /* + register_func >(); + register_func >(); + register_func >(); + register_func >(); + */ + register_func > >(); + + } else { UG_THROW("NavierStokesFV1: Hanging Nodes not implemented.") diff --git a/incompressible/fv1/navier_stokes_fv1.h b/incompressible/fv1/navier_stokes_fv1.h index d64f37a..b0b3d38 100644 --- a/incompressible/fv1/navier_stokes_fv1.h +++ b/incompressible/fv1/navier_stokes_fv1.h @@ -30,6 +30,7 @@ * GNU Lesser General Public License for more details. */ + #ifndef __H__UG__PLUGINS__NAVIER_STOKES__INCOMPRESSIBLE__FV1__NAVIER_STOKES_FV1__ #define __H__UG__PLUGINS__NAVIER_STOKES__INCOMPRESSIBLE__FV1__NAVIER_STOKES_FV1__ @@ -47,8 +48,10 @@ #include "stabilization.h" namespace ug{ + namespace NavierStokes{ + /// \ingroup lib_disc_elem_disc /// @{ @@ -563,6 +566,9 @@ class NavierStokesFV1 virtual void init(); protected: + /// current shape function set (needed for GeomProvider::get()) + LFEID m_LFEID; + /// register utils /// \{ virtual void register_all_funcs(bool bHang); diff --git a/incompressible/fv1/navier_stokes_fv1_FV1.cpp b/incompressible/fv1/navier_stokes_fv1_FV1.cpp new file mode 100644 index 0000000..65db59d --- /dev/null +++ b/incompressible/fv1/navier_stokes_fv1_FV1.cpp @@ -0,0 +1,1130 @@ +/* + * Copyright (c) 2010-2014: G-CSC, Goethe University Frankfurt + * Author: Andreas Vogel + * + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#include "navier_stokes_fv1.h" + +#include "lib_disc/spatial_disc/disc_util/fv1_geom.h" +//#include "lib_disc/spatial_disc/disc_util/fv1FT_geom.h" +#include "lib_disc/spatial_disc/disc_util/geom_provider.h" +//#include "moving_particle/interface_handler_particle.h" + +namespace ug{ + +//template +//class InterfaceHandlerLocalParticle; + +namespace NavierStokes{ + +//////////////////////////////////////////////////////////////////////////////// +// Constructor - set default values +//////////////////////////////////////////////////////////////////////////////// + +template +NavierStokesFV1::NavierStokesFV1(const char* functions, + const char* subsets) +: IncompressibleNavierStokesBase(functions, subsets) +{ + init(); +}; + +template +NavierStokesFV1::NavierStokesFV1(const std::vector& vFct, + const std::vector& vSubset) +: IncompressibleNavierStokesBase(vFct, vSubset) +{ + init(); +}; + + +template +void NavierStokesFV1::init() +{ +// check number of functions + if(this->num_fct() != dim+1) + UG_THROW("Wrong number of functions: The ElemDisc 'NavierStokes'" + " needs exactly "<register_import(m_imSourceSCV); + this->register_import(m_imSourceSCVF); + this->register_import(m_imKinViscosity); + this->register_import(m_imDensitySCVF); + this->register_import(m_imDensitySCV); + + m_imSourceSCV.set_rhs_part(); + m_imSourceSCVF.set_rhs_part(); + m_imDensitySCV.set_mass_part(); + + // default value for density + base_type::set_density(1.0); + + // update assemble functions + register_all_funcs(false); + +} + +template +void NavierStokesFV1:: +prepare_setting(const std::vector& vLfeID, bool bNonRegularGrid) +{ + if(bNonRegularGrid) + UG_THROW("NavierStokes: only regular grid implemented."); + +// check number + if(vLfeID.size() != dim+1) + UG_THROW("NavierStokes: Need exactly "< +void NavierStokesFV1:: +set_kinematic_viscosity(SmartPtr > data) +{ + m_imKinViscosity.set_data(data); +} + +template +void NavierStokesFV1:: +set_density(SmartPtr > data) +{ + m_imDensitySCVF.set_data(data); + m_imDensitySCV.set_data(data); +} + +template +void NavierStokesFV1:: +set_source(SmartPtr, dim> > data) +{ + m_imSourceSCV.set_data(data); + m_imSourceSCVF.set_data(data); +} + +//////////////////////////////////////////////////////////////////////////////// +// assembling functions +//////////////////////////////////////////////////////////////////////////////// + +template +template +void NavierStokesFV1:: +prep_elem_loop(const ReferenceObjectID roid, const int si) +{ +// Only first order implementation + if(!(TFVGeom::order == 1)) + UG_THROW("Only first order implementation, but other Finite Volume" + " Geometry set."); + +// check, that stabilization has been set + if(m_spStab.invalid()) + UG_THROW("Stabilization has not been set."); + +// init stabilization for element type + m_spStab->template set_geometry_type(); + + if (! m_bStokes) // no convective terms in the Stokes eq. => no upwinding + { + // check, that convective upwinding has been set + if(m_spConvStab.invalid() && m_spConvUpwind.invalid()) + UG_THROW("Upwinding for convective Term in Momentum eq. not set."); + + // init convection stabilization for element type + if(m_spConvStab.valid()) + m_spConvStab->template set_geometry_type(); + + // init convection stabilization for element type + if(m_spConvUpwind.valid()) + m_spConvUpwind->template set_geometry_type(); + } + +// check, that kinematic Viscosity has been set + if(!m_imKinViscosity.data_given()) + UG_THROW("NavierStokes::prep_elem_loop:" + " Kinematic Viscosity has not been set, but is required."); + +// check, that Density has been set + if(!m_imDensitySCVF.data_given()) + UG_THROW("NavierStokes::prep_elem_loop:" + " Density has not been set, but is required."); + +// check, that Density has been set + if(!m_imDensitySCV.data_given()) + UG_THROW("NavierStokes::prep_elem_loop:" + " Density has not been set, but is required."); + +// set local positions for imports + if(!TFVGeom::usesHangingNodes) + { + static const int refDim = TElem::dim; + TFVGeom& geo = GeomProvider::get(); + const MathVector* vSCVFip = geo.scvf_local_ips(); + const size_t numSCVFip = geo.num_scvf_ips(); + const MathVector* vSCVip = geo.scv_local_ips(); + const size_t numSCVip = geo.num_scv_ips(); + m_imKinViscosity.template set_local_ips(vSCVFip,numSCVFip); + m_imDensitySCVF.template set_local_ips(vSCVFip,numSCVFip); + m_imDensitySCV.template set_local_ips(vSCVip,numSCVip); + m_imSourceSCV.template set_local_ips(vSCVip,numSCVip); + m_imSourceSCVF.template set_local_ips(vSCVFip,numSCVFip); + } + +} + +template +template +void NavierStokesFV1:: +fsh_elem_loop() +{} + + +template +template +void NavierStokesFV1:: +prep_elem(const LocalVector& u, GridObject* elem, ReferenceObjectID roid, const MathVector vCornerCoords[]) +{ +// Update Geometry for this element + TFVGeom& geo = GeomProvider::get(); + try{ + geo.update(elem, vCornerCoords, &(this->subset_handler())); + } + UG_CATCH_THROW("NavierStokes::prep_elem:" + " Cannot update Finite Volume Geometry."); + +// set local positions for imports + if(TFVGeom::usesHangingNodes) + { + // request ip series + static const int refDim = TElem::dim; + const MathVector* vSCVFip = geo.scvf_local_ips(); + const size_t numSCVFip = geo.num_scvf_ips(); + const MathVector* vSCVip = geo.scv_local_ips(); + const size_t numSCVip = geo.num_scv_ips(); + m_imKinViscosity.template set_local_ips(vSCVFip,numSCVFip); + m_imDensitySCVF.template set_local_ips(vSCVFip,numSCVFip); + m_imDensitySCV.template set_local_ips(vSCVip,numSCVip); + m_imSourceSCV.template set_local_ips(vSCVip,numSCVip); + m_imSourceSCVF.template set_local_ips(vSCVFip,numSCVFip); + + } + +// set global positions for imports + const MathVector* vSCVFip = geo.scvf_global_ips(); + const size_t numSCVFip = geo.num_scvf_ips(); + const MathVector* vSCVip = geo.scv_global_ips(); + const size_t numSCVip = geo.num_scv_ips(); + m_imKinViscosity.set_global_ips(vSCVFip, numSCVFip); + m_imDensitySCVF.set_global_ips(vSCVFip, numSCVFip); + m_imDensitySCV.set_global_ips(vSCVip, numSCVip); + m_imSourceSCV.set_global_ips(vSCVip, numSCVip); + m_imSourceSCVF.set_global_ips(vSCVFip, numSCVFip); +} + +template +template +void NavierStokesFV1:: +add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) +{ +// Only first order implementation + UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); + +// get finite volume geometry + static const TFVGeom& geo = GeomProvider::get(); + +// check for source term to pass to the stabilization + const DataImport, dim>* pSource = NULL; + if(m_imSourceSCVF.data_given()) pSource = &m_imSourceSCVF; + +// check for solutions to pass to stabilization in time-dependent case + const LocalVector *pSol = &u, *pOldSol = NULL; + number dt = 0.0; + if(this->is_time_dependent()) + { + // get and check current and old solution + const LocalVectorTimeSeries* vLocSol = this->local_time_solutions(); + if(vLocSol->size() != 2) + UG_THROW("NavierStokes::add_jac_A_elem: " + " Stabilization needs exactly two time points."); + + // remember local solutions + pSol = &vLocSol->solution(0); + pOldSol = &vLocSol->solution(1); + dt = vLocSol->time(0) - vLocSol->time(1); + } + +// interpolate velocity at ip with standard lagrange interpolation + static const size_t numSCVF = TFVGeom::numSCVF; +// static const size_t numSCVF = TFVGeom::maxNumSCVF; + + MathVector StdVel[numSCVF]; + for(size_t ip = 0; ip < geo.num_scvf(); ++ip) + { + const typename TFVGeom::SCVF& scvf = geo.scvf(ip); + VecSet(StdVel[ip], 0.0); + + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + for(int d1 = 0; d1 < dim; ++d1) + StdVel[ip][d1] += u(d1, sh) * scvf.shape(sh); + } + +// compute stabilized velocities and shapes for continuity equation + m_spStab->update(&geo, *pSol, StdVel, m_bStokes, m_imKinViscosity, m_imDensitySCVF, pSource, pOldSol, dt); + + if (! m_bStokes) // no convective terms in the Stokes eq. => no upwinding + { + // compute stabilized velocities and shapes for convection upwind + if(m_spConvStab.valid()) + if(m_spConvStab != m_spStab) + m_spConvStab->update(&geo, *pSol, StdVel, false, m_imKinViscosity, m_imDensitySCVF, pSource, pOldSol, dt); + + // compute upwind shapes + if(m_spConvUpwind.valid()) + if(m_spStab->upwind() != m_spConvUpwind) + m_spConvUpwind->update(&geo, StdVel); + } + +// get a const (!!) reference to the stabilization + const INavierStokesFV1Stabilization& stab = *m_spStab; + const INavierStokesFV1Stabilization& convStab = *m_spConvStab; + const INavierStokesUpwind& upwind = *m_spConvUpwind; + +// loop Sub Control Volume Faces (SCVF) + for(size_t ip = 0; ip < geo.num_scvf(); ++ip) + { + // get current SCVF + const typename TFVGeom::SCVF& scvf = geo.scvf(ip); + + // loop shape functions + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + { + //////////////////////////////////////////////////// + //////////////////////////////////////////////////// + // Momentum Equation (conservation of momentum) + //////////////////////////////////////////////////// + //////////////////////////////////////////////////// + + //////////////////////////////////////////////////// + // Diffusive Term (Momentum Equation) + //////////////////////////////////////////////////// + + // Compute flux derivative at IP + const number flux_sh = -1.0 * m_imKinViscosity[ip] * m_imDensitySCVF[ip] + * VecDot(scvf.global_grad(sh), scvf.normal()); + + // Add flux derivative to local matrix + for(int d1 = 0; d1 < dim; ++d1) + { + J(d1, scvf.from(), d1, sh) += flux_sh; + J(d1, scvf.to() , d1, sh) -= flux_sh; + } + + if(!m_bLaplace) + { + for(int d1 = 0; d1 < dim; ++d1) + for(int d2 = 0; d2 < dim; ++d2) + { + const number flux2_sh = -1.0 * m_imKinViscosity[ip] * m_imDensitySCVF[ip] + * scvf.global_grad(sh)[d1] * scvf.normal()[d2]; + J(d1, scvf.from(), d2, sh) += flux2_sh; + J(d1, scvf.to() , d2, sh) -= flux2_sh; + } + } + + //////////////////////////////////////////////////// + // Pressure Term (Momentum Equation) + //////////////////////////////////////////////////// + + // Add flux derivative for local matrix + for(int d1 = 0; d1 < dim; ++d1) + { + const number flux_sh = scvf.shape(sh) * scvf.normal()[d1]; + J(d1, scvf.from(), _P_, sh) += flux_sh; + J(d1, scvf.to() , _P_, sh) -= flux_sh; + } + + //////////////////////////////////////////////////// + // Convective Term (Momentum Equation) + //////////////////////////////////////////////////// + + // note: StdVel will be the advecting velocity (not upwinded) + // UpwindVel/StabVel will be the transported velocity + + if (! m_bStokes) // no convective terms in the Stokes equation + { + // compute upwind velocity + MathVector UpwindVel; + + // switch PAC + if(m_spConvUpwind.valid()) UpwindVel = upwind.upwind_vel(ip, u, StdVel); + else if (m_spConvStab.valid()) UpwindVel = convStab.stab_vel(ip); + else UG_THROW("Cannot find upwind for convective term."); + + // peclet blend + number w = 1.0; + if(m_bPecletBlend) + w = peclet_blend(UpwindVel, geo, ip, StdVel[ip], m_imKinViscosity[ip]); + + // compute product of stabilized vel and normal + const number prod = VecProd(StdVel[ip], scvf.normal()) * m_imDensitySCVF[ip]; + + /////////////////////////////////// + // Add fixpoint linearization + /////////////////////////////////// + + // Stabilization used as upwind + if(m_spConvStab.valid()) + { + // velocity derivatives + if(stab.vel_comp_connected()) + for(int d1 = 0; d1 < dim; ++d1) + for(int d2 = 0; d2 < dim; ++d2) + { + const number convFlux_vel = prod * w * convStab.stab_shape_vel(ip, d1, d2, sh); + J(d1, scvf.from(), d2, sh) += convFlux_vel; + J(d1, scvf.to() , d2, sh) -= convFlux_vel; + } + else + for(int d1 = 0; d1 < dim; ++d1) + { + const number convFlux_vel = prod * w * convStab.stab_shape_vel(ip, d1, d1, sh); + J(d1, scvf.from(), d1, sh) += convFlux_vel; + J(d1, scvf.to() , d1, sh) -= convFlux_vel; + } + + // pressure derivative + for(int d1 = 0; d1 < dim; ++d1) + { + const number convFlux_p = prod * w * convStab.stab_shape_p(ip, d1, sh); + + J(d1, scvf.from(), _P_, sh) += convFlux_p; + J(d1, scvf.to() , _P_, sh) -= convFlux_p; + } + } + + // Upwind used as upwind + if(m_spConvUpwind.valid()) + { + number convFlux_vel = upwind.upwind_shape_sh(ip, sh); + + // in some cases (e.g. PositiveUpwind, RegularUpwind) the upwind + // velocity in an ip depends also on the upwind velocity in + // other ips. This is reflected by the fact, that the ip + // shapes are non-zero. In that case, we can interpolate an + // approximate upwind only from the corner velocities by using + // u_up = \sum shape_co U_co + \sum shape_ip \tilde{u}_ip + // = \sum shape_co U_co + \sum \sum shape_ip norm_shape_co|_ip * U_co + if(m_spConvUpwind->non_zero_shape_ip()) + { + for(size_t ip2 = 0; ip2 < geo.num_scvf(); ++ip2) + { + const typename TFVGeom::SCVF& scvf2 = geo.scvf(ip2); + convFlux_vel += scvf2.shape(sh) * upwind.upwind_shape_ip(ip, ip2); + } + } + + convFlux_vel *= prod * w; + + for(int d1 = 0; d1 < dim; ++d1) + { + J(d1, scvf.from(), d1, sh) += convFlux_vel; + J(d1, scvf.to() , d1, sh) -= convFlux_vel; + } + } + + // derivative due to peclet blending + if(m_bPecletBlend) + { + const number convFluxPe = prod * (1.0-w) * scvf.shape(sh); + for(int d1 = 0; d1 < dim; ++d1) + { + J(d1, scvf.from(), d1, sh) += convFluxPe; + J(d1, scvf.to() , d1, sh) -= convFluxPe; + } + } + + ///////////////////////////////////////// + // Add full jacobian (remaining part) + ///////////////////////////////////////// + + // Add remaining term for exact jacobian + if(m_bFullNewtonFactor) + { + // Stabilization used as upwind + if(m_spConvStab.valid()) + { + // loop defect components + for(int d1 = 0; d1 < dim; ++d1) + { + for(int d2 = 0; d2 < dim; ++d2) + { + // derivatives w.r.t. velocity + // Compute n * derivs + number prod_vel = 0.0; + + // Compute sum_j n_j * \partial_{u_i^sh} u_j + if(stab.vel_comp_connected()) + for(size_t k = 0; k < (size_t)dim; ++k) + prod_vel += w * convStab.stab_shape_vel(ip, k, d2, sh) + * scvf.normal()[k]; + else + prod_vel = convStab.stab_shape_vel(ip, d1, d1, sh) + * scvf.normal()[d1]; + + prod_vel *= m_bFullNewtonFactor * m_imDensitySCVF[ip]; + + J(d1, scvf.from(), d2, sh) += prod_vel * UpwindVel[d1]; + J(d1, scvf.to() , d2, sh) -= prod_vel * UpwindVel[d1]; + } + + // derivative w.r.t pressure + // Compute n * derivs + number prod_p = 0.0; + + // Compute sum_j n_j * \parial_{u_i^sh} u_j + for(int k = 0; k < dim; ++k) + prod_p += convStab.stab_shape_p(ip, k, sh) + * scvf.normal()[k]; + + prod_p *= m_bFullNewtonFactor * m_imDensitySCVF[ip]; + + J(d1, scvf.from(), _P_, sh) += prod_p * UpwindVel[d1]; + J(d1, scvf.to() , _P_, sh) -= prod_p * UpwindVel[d1]; + } + } + + // Upwind used as upwind + if(m_spConvUpwind.valid()) + { + // loop defect components + for(int d1 = 0; d1 < dim; ++d1) + for(int d2 = 0; d2 < dim; ++d2) + { + // derivatives w.r.t. velocity + number prod_vel = w * upwind.upwind_shape_sh(ip,sh) + * scvf.normal()[d2] * m_imDensitySCVF[ip]; + + J(d1, scvf.from(), d2, sh) += prod_vel * UpwindVel[d1]; + J(d1, scvf.to() , d2, sh) -= prod_vel * UpwindVel[d1]; + } + } + + // derivative due to peclet blending + if(m_bPecletBlend) + { + for(int d1 = 0; d1 < dim; ++d1) + for(int d2 = 0; d2 < dim; ++d2) + { + const number convFluxPe = UpwindVel[d1] * (1.0-w) + * scvf.shape(sh) + * scvf.normal()[d2] + * m_imDensitySCVF[ip]; + J(d1, scvf.from(), d2, sh) += convFluxPe; + J(d1, scvf.to() , d2, sh) -= convFluxPe; + } + } + } // end exact jacobian part + + } // end of if (! m_bStokes) for the convective terms + + //////////////////////////////////////////////////// + //////////////////////////////////////////////////// + // Continuity Equation (conservation of mass) + //////////////////////////////////////////////////// + //////////////////////////////////////////////////// + + // Add derivative of stabilized flux w.r.t velocity comp to local matrix + if(stab.vel_comp_connected()) + { + for(int d1 = 0; d1 < dim; ++d1) + { + number contFlux_vel = 0.0; + for(int d2 = 0; d2 < dim; ++d2) + contFlux_vel += stab.stab_shape_vel(ip, d2, d1, sh) + * scvf.normal()[d2] * m_imDensitySCVF[ip]; + + J(_P_, scvf.from(), d1, sh) += contFlux_vel; + J(_P_, scvf.to() , d1, sh) -= contFlux_vel; + } + } + else + { + for(int d1 = 0; d1 < dim; ++d1) + { + const number contFlux_vel = stab.stab_shape_vel(ip, d1, d1, sh) + * scvf.normal()[d1] * m_imDensitySCVF[ip]; + + J(_P_, scvf.from(), d1, sh) += contFlux_vel; + J(_P_, scvf.to() , d1, sh) -= contFlux_vel; + } + } + + // Add derivative of stabilized flux w.r.t pressure to local matrix + number contFlux_p = 0.0; + for(int d1 = 0; d1 < dim; ++d1) + contFlux_p += stab.stab_shape_p(ip, d1, sh) * scvf.normal()[d1] * m_imDensitySCVF[ip]; + + J(_P_, scvf.from(), _P_, sh) += contFlux_p; + J(_P_, scvf.to() , _P_, sh) -= contFlux_p; + } + } +} + +template +template +void NavierStokesFV1:: +add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) +{ + //UG_LOG("Anfang add_def_A_elem"); + +// Only first order implemented + UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); + +// get finite volume geometry + static const TFVGeom& geo = GeomProvider::get(); + +// check for source term to pass to the stabilization + const DataImport, dim>* pSource = NULL; + if(m_imSourceSCVF.data_given()) pSource = &m_imSourceSCVF; + +// check for solutions to pass to stabilization in time-dependent case + const LocalVector *pSol = &u, *pOldSol = NULL; + number dt = 0.0; + if(this->is_time_dependent()) + { + // get and check current and old solution + const LocalVectorTimeSeries* vLocSol = this->local_time_solutions(); + if(vLocSol->size() != 2) + UG_THROW("NavierStokes::add_def_A_elem: " + " Stabilization needs exactly two time points."); + + // remember local solutions + pSol = &vLocSol->solution(0); + pOldSol = &vLocSol->solution(1); + dt = vLocSol->time(0) - vLocSol->time(1); + } + +// interpolate velocity at ip with standard lagrange interpolation + + static const size_t numSCVF = TFVGeom::numSCVF; + // static const size_t numSCVF = TFVGeom::maxNumSCVF; + + MathVector StdVel[numSCVF]; + for(size_t ip = 0; ip < geo.num_scvf(); ++ip) + { + const typename TFVGeom::SCVF& scvf = geo.scvf(ip); + VecSet(StdVel[ip], 0.0); + + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + for(int d1 = 0; d1 < dim; ++d1) + StdVel[ip][d1] += u(d1, sh) * scvf.shape(sh); + } + +// compute stabilized velocities and shapes for continuity equation + // \todo: (optional) Here we can skip the computation of shapes, implement? + m_spStab->update(&geo, *pSol, StdVel, m_bStokes, m_imKinViscosity, m_imDensitySCVF, pSource, pOldSol, dt); + + if (! m_bStokes) // no convective terms in the Stokes eq. => no upwinding + { + // compute stabilized velocities and shapes for convection upwind + if(m_spConvStab.valid()) + if(m_spConvStab != m_spStab) + m_spConvStab->update(&geo, *pSol, StdVel, false, m_imKinViscosity, m_imDensitySCVF, pSource, pOldSol, dt); + + // compute upwind shapes + if(m_spConvUpwind.valid()) + if(m_spStab->upwind() != m_spConvUpwind) + m_spConvUpwind->update(&geo, StdVel); + } + +// get a const (!!) reference to the stabilization + const INavierStokesFV1Stabilization& stab = *m_spStab; + const INavierStokesFV1Stabilization& convStab = *m_spConvStab; + const INavierStokesUpwind& upwind = *m_spConvUpwind; + +// loop Sub Control Volume Faces (SCVF) + for(size_t ip = 0; ip < geo.num_scvf(); ++ip) + { + // get current SCVF + const typename TFVGeom::SCVF& scvf = geo.scvf(ip); + + //////////////////////////////////////////////////// + //////////////////////////////////////////////////// + // Momentum Equation (conservation of momentum) + //////////////////////////////////////////////////// + //////////////////////////////////////////////////// + + // \todo: we could also add all fluxes at once in order to save several + // accesses to the local defect, implement and loose clarity? + + //////////////////////////////////////////////////// + // Diffusive Term (Momentum Equation) + //////////////////////////////////////////////////// + + // 1. Interpolate Functional Matrix of velocity at ip + MathMatrix gradVel; + for(int d1 = 0; d1 < dim; ++d1) + for(int d2 = 0; d2 diffFlux; + + // Add (\nabla u) \cdot \vec{n} + MatVecMult(diffFlux, gradVel, scvf.normal()); + + // Add (\nabla u)^T \cdot \vec{n} + if(!m_bLaplace) + TransposedMatVecMultAdd(diffFlux, gradVel, scvf.normal()); + + // scale by viscosity + VecScale(diffFlux, diffFlux, (-1.0) * m_imKinViscosity[ip] * m_imDensitySCVF[ip]); + + // 3. Add flux to local defect + for(int d1 = 0; d1 < dim; ++d1) + { + d(d1, scvf.from()) += diffFlux[d1]; + d(d1, scvf.to() ) -= diffFlux[d1]; + } + + //////////////////////////////////////////////////// + // Convective Term (Momentum Equation) + //////////////////////////////////////////////////// + + // note: StdVel will be the advecting velocity (not upwinded) + // UpwindVel/StabVel will be the transported velocity + + if (! m_bStokes) // no convective terms in the Stokes equation + { + // find the upwind velocity at ip + MathVector UpwindVel; + + // switch PAC + if(m_spConvUpwind.valid()) UpwindVel = upwind.upwind_vel(ip, u, StdVel); + else if (m_spConvStab.valid()) UpwindVel = convStab.stab_vel(ip); + else UG_THROW("Cannot find upwind for convective term."); + + // Peclet Blend + if(m_bPecletBlend) + peclet_blend(UpwindVel, geo, ip, StdVel[ip], m_imKinViscosity[ip]); + + // compute product of standard velocity and normal + const number prod = VecProd(StdVel[ip], scvf.normal()) * m_imDensitySCVF[ip]; + + // Add contributions to local velocity components + for(int d1 = 0; d1 < dim; ++d1) + { + d(d1, scvf.from()) += UpwindVel[d1] * prod; + d(d1, scvf.to() ) -= UpwindVel[d1] * prod; + } + } + + //////////////////////////////////////////////////// + // Pressure Term (Momentum Equation) + //////////////////////////////////////////////////// + + // 1. Interpolate pressure at ip + number pressure = 0.0; + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + pressure += scvf.shape(sh) * u(_P_, sh); + + // 2. Add contributions to local defect + for(int d1 = 0; d1 < dim; ++d1) + { + d(d1, scvf.from()) += pressure * scvf.normal()[d1]; + d(d1, scvf.to() ) -= pressure * scvf.normal()[d1]; + } + + //////////////////////////////////////////////////// + //////////////////////////////////////////////////// + // Continuity Equation (conservation of mass) + //////////////////////////////////////////////////// + //////////////////////////////////////////////////// + + // compute flux at ip + const number contFlux = VecProd(stab.stab_vel(ip), scvf.normal()) * m_imDensitySCVF[ip]; + + // Add contributions to local defect + d(_P_, scvf.from()) += contFlux; + d(_P_, scvf.to() ) -= contFlux; + } +} + + +template +template +void NavierStokesFV1:: +add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) +{ +// Only first order implementation + UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); + +// get finite volume geometry + static const TFVGeom& geo = GeomProvider::get(); + +// loop Sub Control Volumes (SCV) + for(size_t ip = 0; ip < geo.num_scv(); ++ip) + { + // get SCV + const typename TFVGeom::SCV& scv = geo.scv(ip); + + // get associated node + const int sh = scv.node_id(); + + // loop velocity components + for(int d1 = 0; d1 < dim; ++d1) + { + // Add to local matrix + J(d1, sh, d1, sh) += scv.volume() * m_imDensitySCV[ip]; + } + } +} + + +template +template +void NavierStokesFV1:: +add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) +{ +// Only first order implementation + UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); + +// get finite volume geometry + static const TFVGeom& geo = GeomProvider::get(); + +// loop Sub Control Volumes (SCV) + for(size_t ip = 0; ip < geo.num_scv(); ++ip) + { + // get current SCV + const typename TFVGeom::SCV& scv = geo.scv(ip); + + // get associated node + const int sh = scv.node_id(); + + // loop velocity components + for(int d1 = 0; d1 < dim; ++d1) + { + // Add to local matrix + d(d1, sh) += u(d1, sh) * scv.volume() * m_imDensitySCV[ip]; + } + } +} + + +template +template +void NavierStokesFV1:: +add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoords[]) +{ +// Only first order implementation + UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); + +// if zero data given, return + if(!m_imSourceSCV.data_given()) return; + +// get finite volume geometry + static const TFVGeom& geo = GeomProvider::get(); + +// loop Sub Control Volumes (SCV) + for(size_t ip = 0; ip < geo.num_scv(); ++ip) + { + // get current SCV + const typename TFVGeom::SCV& scv = geo.scv(ip); + + // get associated node + const int sh = scv.node_id(); + + // Add to local rhs + for(int d1 = 0; d1 < dim; ++d1){ + d(d1, sh) += m_imSourceSCV[ip][d1] * scv.volume() * m_imDensitySCV[ip]; + } + } +} + +template +template +inline +number +NavierStokesFV1:: +peclet_blend(MathVector& UpwindVel, const TFVGeom& geo, size_t ip, + const MathVector& StdVel, number kinVisco) +{ + const typename TFVGeom::SCVF& scvf = geo.scvf(ip); +// compute peclet number + number Pe = VecProd(StdVel, scvf.normal())/VecTwoNormSq(scvf.normal()) + * VecDistance(geo.corners() [scvf.to()], geo.corners() [scvf.from()]) / kinVisco; + +// compute weight + const number Pe2 = Pe * Pe; + const number w = Pe2 / (5.0 + Pe2); + +// compute upwind vel + VecScaleAdd(UpwindVel, w, UpwindVel, (1.0-w), StdVel); + + return w; +} + +// computes the linearized defect w.r.t to the velocity +template +template +void NavierStokesFV1:: +ex_velocity_grad(MathMatrix vValue[], + const MathVector vGlobIP[], + number time, int si, + const LocalVector& u, + GridObject* elem, + const MathVector vCornerCoords[], + const MathVector vLocIP[], + const size_t nip, + bool bDeriv, + std::vector > > vvvDeriv[]) +{ +// Get finite volume geometry + static const TFVGeom& geo = GeomProvider::get(); + +// reference element + typedef typename reference_element_traits::reference_element_type ref_elem_type; + +// reference dimension + static const int refDim = ref_elem_type::dim; + +// number of shape functions + static const size_t numSH = ref_elem_type::numCorners; + +// FV1 SCVF ip + if(vLocIP == geo.scvf_local_ips()) + { + // Loop Sub Control Volume Faces (SCVF) + for (size_t ip = 0; ip < geo.num_scvf(); ++ip) + { + // Get current SCVF + const typename TFVGeom::SCVF& scvf = geo.scvf(ip); + + // Loop dimensions for direction + for(int d1 = 0; d1 < dim; ++d1) + { + // Loop dimensions for derivative + for(int d2 = 0; d2 & rTrialSpace = Provider >::get(); + + // storage for shape function at ip + MathVector vLocGrad[numSH]; + + // Reference Mapping + MathMatrix JTInv; + ReferenceMapping mapping(vCornerCoords); + + // loop ips + for(size_t ip = 0; ip < nip; ++ip) + { + // evaluate at shapes at ip + rTrialSpace.grads(vLocGrad, vLocIP[ip]); + + // Loop dimensions for direction + for(int d1 = 0; d1 < dim; ++d1) + { + // Loop dimensions for derivative + for(int d2 = 0; d2 +void NavierStokesFV1:: +register_all_funcs(bool bHang) +{ + bool bRegisterUsual = true; + +// switch assemble functions + if(!bHang) + { + if ( bRegisterUsual ) + register_func >(); + // else + // register_func > >(); + } + else + { + UG_THROW("NavierStokesFV1: Hanging Nodes not implemented.") + } +} +#endif + +#ifdef UG_DIM_2 +template<> +void NavierStokesFV1:: +register_all_funcs(bool bHang) +{ + bool bRegisterUsual = true; + +// switch assemble functions + if(!bHang) + { + if ( bRegisterUsual ) + { + register_func >(); + register_func >(); + } + // else + // register_func > >(); + } + else + { + UG_THROW("NavierStokesFV1: Hanging Nodes not implemented.") + } +} +#endif + +#ifdef UG_DIM_3 +template<> +void NavierStokesFV1:: +register_all_funcs(bool bHang) +{ + bool bRegisterUsual = true; + +// switch assemble functions + if(!bHang) + { + if ( bRegisterUsual ) + { + register_func >(); + register_func >(); + register_func >(); + register_func >(); + } + // else + // register_func > >(); + } + else + { + UG_THROW("NavierStokesFV1: Hanging Nodes not implemented.") + } + +} + +#endif + +template +template +void +NavierStokesFV1:: +register_func() +{ + ReferenceObjectID id = geometry_traits::REFERENCE_OBJECT_ID; + typedef this_type T; + static const int refDim = reference_element_traits::dim; + + this->clear_add_fct(id); + this->set_prep_elem_loop_fct( id, &T::template prep_elem_loop); + this->set_prep_elem_fct( id, &T::template prep_elem); + this->set_fsh_elem_loop_fct( id, &T::template fsh_elem_loop); + this->set_add_jac_A_elem_fct( id, &T::template add_jac_A_elem); + this->set_add_jac_M_elem_fct( id, &T::template add_jac_M_elem); + this->set_add_def_A_elem_fct( id, &T::template add_def_A_elem); + this->set_add_def_M_elem_fct( id, &T::template add_def_M_elem); + this->set_add_rhs_elem_fct( id, &T::template add_rhs_elem); + + m_exVelocityGrad->template set_fct(id, this, &T::template ex_velocity_grad); + +} + +//////////////////////////////////////////////////////////////////////////////// +// explicit template instantiations +//////////////////////////////////////////////////////////////////////////////// + +#ifdef UG_DIM_2 +template class NavierStokesFV1; +#endif +#ifdef UG_DIM_3 +template class NavierStokesFV1; +#endif + +} // namespace NavierStokes +} // namespace ug diff --git a/incompressible/fv1/stabilization.cpp b/incompressible/fv1/stabilization.cpp index 7ddd0e2..8499bbe 100644 --- a/incompressible/fv1/stabilization.cpp +++ b/incompressible/fv1/stabilization.cpp @@ -124,6 +124,291 @@ template void NavierStokesFIELDSStabilization:: update(const FV1Geometry* geo, + const LocalVector& vCornerValue, + const MathVector vStdVel[], + const bool bStokes, + const DataImport& kinVisco, + const DataImport& density, + const DataImport, dim>* pSource, + const LocalVector* pvCornerValueOldTime, number dt) +{ + // abbreviation for pressure + static const size_t _P_ = dim; + + // Some constants + static const size_t numIp = FV1Geometry::numSCVF; + static const size_t numSh = FV1Geometry::numSCV; + + // compute upwind (no convective terms for the Stokes eq. => no upwind) + if (! bStokes) this->compute_upwind(geo, vStdVel); + + // compute diffusion length + this->compute_diff_length(*geo); + + // cache values + number vViscoPerDiffLenSq[numIp]; + for(size_t ip = 0; ip < numIp; ++ip) + vViscoPerDiffLenSq[ip] = kinVisco[ip] * diff_length_sq_inv(ip); + + number vNormStdVelPerConvLen[numIp]; + if(!bStokes) + for(size_t ip = 0; ip < numIp; ++ip) + vNormStdVelPerConvLen[ip] = VecTwoNorm(vStdVel[ip]) / upwind_conv_length(ip); + + // Find out if upwinded velocities depend on other ip velocities. In that case + // we have to solve a matrix system. Else the system is diagonal and we can + // compute the inverse directly + + // diagonal case (i.e. upwind vel depend only on corner vel or no upwind) + if(bStokes || !non_zero_shape_ip()) + { + // We can solve the systems ip by ip + for(size_t ip = 0; ip < numIp; ++ip) + { + // get SubControlVolumeFace + const typename FV1Geometry::SCVF& scvf = geo->scvf(ip); + + // First, we compute the contributions to the diagonal + // Note: - There is no contribution of the upwind vel to the diagonal + // in this case, only for non-diag problems + // - The diag does not depend on the dimension + + // Diffusion part + number diag = vViscoPerDiffLenSq[ip]; + + // Time part + if(pvCornerValueOldTime != NULL) + diag += 1./dt; + + // Convective Term (no convective terms in the Stokes eq.) + if (! bStokes) + diag += vNormStdVelPerConvLen[ip]; + + // Loop components of velocity + for(size_t d = 0; d < (size_t)dim; d++) + { + // Now, we can assemble the rhs. This rhs is assembled by all + // terms, that are non-dependent on the ip vel. + // Note, that we can compute the stab_shapes on the fly when setting + // up the system. + + // Source + number rhs = 0.0; + if(pSource != NULL) + rhs = (*pSource)[ip][d]; + + // Time + if(pvCornerValueOldTime != NULL) + { + // interpolate old time step + number oldIPVel = 0.0; + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + oldIPVel += scvf.shape(sh) * (*pvCornerValueOldTime)(d, sh); + + // add to rhs + rhs += oldIPVel / dt; + } + + // loop shape functions + for(size_t k = 0; k < scvf.num_sh(); ++k) + { + // Diffusion part + number sumVel = vViscoPerDiffLenSq[ip] * scvf.shape(k); + + // Convective term + if (! bStokes) // no convective terms in the Stokes eq. + sumVel += vNormStdVelPerConvLen[ip] * upwind_shape_sh(ip, k); + + // Add to rhs + rhs += sumVel * vCornerValue(d, k); + + // set stab shape + stab_shape_vel(ip, d, d, k) = sumVel / diag; + + // Pressure part + const number sumP = -1.0 * (scvf.global_grad(k))[d] / density[ip]; + + // Add to rhs + rhs += sumP * vCornerValue(_P_, k); + + // set stab shape + stab_shape_p(ip, d, k) = sumP / diag; + } + + // Finally, the can invert this row + stab_vel(ip)[d] = rhs / diag; + } + } + } + /// need to solve system + else + { + // For the FIELDS stabilization, there is no connection between the + // velocity components. Thus we can solve a system of size=numIP for + // each component of the velocity separately. This results in smaller + // matrices, that we have to invert. + + // First, we have to assemble the Matrix, that includes all connections + // between the ip velocity component. Note, that in this case the + // matrix is non-diagonal and we must invert it. + // The Matrix is the same for all dim-components, thus we assemble it only + // once + + // size of the system + static const size_t N = numIp; + + // a fixed size matrix + DenseMatrix< FixedArray2 > mat; + + // reset all values of the matrix to zero + mat = 0.0; + + // Loop integration points + for(size_t ip = 0; ip < numIp; ++ip) + { + // Time part + if(pvCornerValueOldTime != NULL) + mat(ip, ip) += 1./dt; + + // Diffusion part + mat(ip, ip) += vViscoPerDiffLenSq[ip]; + + // cache this value + const number scale = vNormStdVelPerConvLen[ip]; + + // Convective Term (standard) + mat(ip, ip) += scale; + + // Convective Term by upwind + for(size_t ip2 = 0; ip2 < numIp; ++ip2) + mat(ip, ip2) -= upwind_shape_ip(ip, ip2) * scale; + } + + // we now create a matrix, where we store the inverse matrix + typename block_traits > >::inverse_type inv; + + // get the inverse + if(!GetInverse(inv, mat)) + UG_THROW("Could not compute inverse."); + + // loop dimensions (i.e. components of the velocity) + for(int d = 0; d < dim; ++d) + { + // create two vectors + DenseVector< FixedArray1 > contVel[numSh]; + DenseVector< FixedArray1 > contP[numSh]; + + // Now, we can create several vector that describes the contribution of the + // corner velocities and the corner pressure. For each of this contribution + // components, we will apply the inverted matrix to get the stab_shapes + + // Loop integration points + for(size_t ip = 0; ip < numIp; ++ip) + { + // get SubControlVolumeFace + const typename FV1Geometry::SCVF& scvf = geo->scvf(ip); + + // loop shape functions + for(size_t k = 0; k < numSh; ++k) + { + // Diffusion part + contVel[k][ip] = vViscoPerDiffLenSq[ip] * scvf.shape(k); + + // Convection part + contVel[k][ip] += vNormStdVelPerConvLen[ip] * upwind_shape_sh(ip, k); + + // Pressure part + contP[k][ip] = -1.0 * (scvf.global_grad(k))[d] / density[ip]; + } + } + + // solution vector + DenseVector< FixedArray1 > xVel, xP; + + // compute all stab_shapes + for(size_t k = 0; k < numSh; ++k) + { + // apply for vel stab_shape + MatMult(xVel, 1.0, inv, contVel[k]); + + // apply for pressure stab_shape + MatMult(xP, 1.0, inv, contP[k]); + + // write values in data structure + //\todo: can we optimize this, e.g. without copy? + for(size_t ip = 0; ip < numIp; ++ip) + { + // write stab_shape for vel + stab_shape_vel(ip, d, d, k) = xVel[ip]; + + // write stab_shape for pressure + stab_shape_p(ip, d, k) = xP[ip]; + } + } + + // Finally, we can compute the values of the stabilized velocity for each + // integration point + + // vector of all contributions + DenseVector< FixedArray1 > f; + + // Loop integration points + for(size_t ip = 0; ip < numIp; ++ip) + { + // get SubControlVolumeFace + const typename FV1Geometry::SCVF& scvf = geo->scvf(ip); + + // Source + f[ip] = 0.0; + if(pSource != NULL) + f[ip] = (*pSource)[ip][d]; + + // Time + if(pvCornerValueOldTime != NULL) + { + // interpolate old time step + // \todo: Is this ok? Or do we need the old stabilized vel ? + number oldIPVel = 0.0; + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + oldIPVel += scvf.shape(sh) * (*pvCornerValueOldTime)(d, sh); + + // add to rhs + f[ip] += oldIPVel / dt; + } + } + + // sum up all contributions of vel and p for rhs. + for(size_t k = 0; k < numSh; ++k) + { + // add velocity contribution + VecScaleAdd(f, 1.0, f, vCornerValue(d, k), contVel[k]); + + // add pressure contribution + VecScaleAdd(f, 1.0, f, vCornerValue(_P_, k), contP[k]); + } + + // invert the system for all contributions + DenseVector< FixedArray1 > x; + MatMult(x, 1.0, inv, f); + + // write values in data structure + //\todo: can we optimize this, e.g. without copy? + for(size_t ip = 0; ip < numIp; ++ip) + { + // write stab_shape for vel + stab_vel(ip)[d] = x[ip]; + } + } // end dim loop + + } // end switch for non-diag +} + + +template +template +void +NavierStokesFIELDSStabilization:: +update(const DimFV1FTGeometry >* geo, const LocalVector& vCornerValue, const MathVector vStdVel[], const bool bStokes, @@ -132,13 +417,25 @@ update(const FV1Geometry* geo, const DataImport, dim>* pSource, const LocalVector* pvCornerValueOldTime, number dt) { + if ( geo->num_scvf() == 0 ) + return; + // abbreviation for pressure static const size_t _P_ = dim; + typedef DimFV1FTGeometry > TFVGeom; + +// hard coded for mat = in else-case! If not, assembling of mat WRONG! + static const size_t maxNumIp = dim+1; //TFVGeom::maxNumSCVF; + static const size_t maxNumSh = dim+1; //TFVGeom::maxNSH; + // Some constants - static const size_t numIp = FV1Geometry::numSCVF; - static const size_t numSh = FV1Geometry::numSCV; + //static const size_t numIp = TFVGeom::numSCVF; + //static const size_t numSh = TFVGeom::numSCV; + const size_t numIp = geo->num_scvf(); + const size_t numSh = geo->num_scv(); + // compute upwind (no convective terms for the Stokes eq. => no upwind) if (! bStokes) this->compute_upwind(geo, vStdVel); @@ -166,7 +463,7 @@ update(const FV1Geometry* geo, for(size_t ip = 0; ip < numIp; ++ip) { // get SubControlVolumeFace - const typename FV1Geometry::SCVF& scvf = geo->scvf(ip); + const typename TFVGeom::SCVF& scvf = geo->scvf(ip); // First, we compute the contributions to the diagonal // Note: - There is no contribution of the upwind vel to the diagonal @@ -243,6 +540,8 @@ update(const FV1Geometry* geo, /// need to solve system else { + UG_THROW("in stabilisation.h: FIELDS::update(): Stop! this case is not implemented for DimFV1FTGeometry!\n"); + // For the FIELDS stabilization, there is no connection between the // velocity components. Thus we can solve a system of size=numIP for // each component of the velocity separately. This results in smaller @@ -255,7 +554,7 @@ update(const FV1Geometry* geo, // once // size of the system - static const size_t N = numIp; + static const size_t N = maxNumIp; //numIp; // a fixed size matrix DenseMatrix< FixedArray2 > mat; @@ -295,8 +594,8 @@ update(const FV1Geometry* geo, for(int d = 0; d < dim; ++d) { // create two vectors - DenseVector< FixedArray1 > contVel[numSh]; - DenseVector< FixedArray1 > contP[numSh]; + DenseVector< FixedArray1 > contVel[maxNumSh]; + DenseVector< FixedArray1 > contP[maxNumSh]; // Now, we can create several vector that describes the contribution of the // corner velocities and the corner pressure. For each of this contribution @@ -306,7 +605,7 @@ update(const FV1Geometry* geo, for(size_t ip = 0; ip < numIp; ++ip) { // get SubControlVolumeFace - const typename FV1Geometry::SCVF& scvf = geo->scvf(ip); + const typename TFVGeom::SCVF& scvf = geo->scvf(ip); // loop shape functions for(size_t k = 0; k < numSh; ++k) @@ -356,7 +655,7 @@ update(const FV1Geometry* geo, for(size_t ip = 0; ip < numIp; ++ip) { // get SubControlVolumeFace - const typename FV1Geometry::SCVF& scvf = geo->scvf(ip); + const typename TFVGeom::SCVF& scvf = geo->scvf(ip); // Source f[ip] = 0.0; @@ -771,6 +1070,354 @@ update(const FV1Geometry* geo, } // end switch for non-diag } +template +template +void +NavierStokesFLOWStabilization:: +update(const DimFV1FTGeometry >* geo, + const LocalVector& vCornerValue, + const MathVector vStdVel[], + const bool bStokes, + const DataImport& kinVisco, + const DataImport& density, + const DataImport, dim>* pSource, + const LocalVector* pvCornerValueOldTime, number dt) +{ + // abbreviation for pressure + static const size_t _P_ = dim; + + typedef DimFV1FTGeometry > TFVGeom; + + // hard coded for mat = in else-case! If not, assembling of mat WRONG! + static const size_t maxNumIp = dim+2; //TFVGeom::maxNumSCVF; + static const size_t maxNumSh = dim+2; //TFVGeom::maxNSH; + + // Some constants + //static const size_t numIp = TFVGeom::numSCVF; + //static const size_t numSh = TFVGeom::numSCV; + const size_t numIp = geo->num_scvf(); + const size_t numSh = geo->num_scv(); + + // compute upwind and downwind (no convective terms for the Stokes eq. => no upwind) + if (! bStokes) + { + this->compute_upwind(geo, vStdVel); + this->compute_downwind(geo, vStdVel); + } + + // compute diffusion length + this->compute_diff_length(*geo); + + // cache values + number vViscoPerDiffLenSq[numIp]; + for(size_t ip = 0; ip < numIp; ++ip) + vViscoPerDiffLenSq[ip] = kinVisco[ip] * diff_length_sq_inv(ip); + + number vNormStdVelPerConvLen[numIp]; + number vNormStdVelPerDownLen[numIp]; + if(!bStokes) + for(size_t ip = 0; ip < numIp; ++ip) + { + const number norm = VecTwoNorm(vStdVel[ip]); + vNormStdVelPerConvLen[ip] = norm / upwind_conv_length(ip); + vNormStdVelPerDownLen[ip] = norm / (downwind_conv_length(ip) + upwind_conv_length(ip)); + } + + // Find out if upwinded velocities depend on other ip velocities. In that case + // we have to solve a matrix system. Else the system is diagonal and we can + // compute the inverse directly + + // diagonal case (i.e. upwind vel depend only on corner vel or no upwind) + if(bStokes || !non_zero_shape_ip()) + { + // Loop integration points + for(size_t ip = 0; ip < numIp; ++ip) + { + // get SubControlVolumeFace + const typename TFVGeom::SCVF& scvf = geo->scvf(ip); + + // First, we compute the contributions to the diagonal + // Note: - There is no contribution of the upwind vel to the diagonal + // in this case, only for non-diag problems + // - The diag does not depend on the dimension + + // the diagonal entry + number diag = vViscoPerDiffLenSq[ip]; + + // Time part + if(pvCornerValueOldTime != NULL) + diag += 1./dt; + + // Convective Term (no convective terms in the Stokes eq.) + if (! bStokes) + diag += vNormStdVelPerConvLen[ip]; + + // Loop components of velocity + for(int d = 0; d < dim; d++) + { + // Now, we can assemble the rhs. This rhs is assembled by all + // terms, that are non-dependent on the ip vel. + // Note, that we can compute the stab_shapes on the fly when setting + // up the system. + + // Source + number rhs = 0.0; + if(pSource != NULL) + rhs = (*pSource)[ip][d]; + + // Time + if(pvCornerValueOldTime != NULL) + { + // interpolate old time step + number oldIPVel = 0.0; + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + oldIPVel += scvf.shape(sh) * (*pvCornerValueOldTime)(d, sh); + + // add to rhs + rhs += oldIPVel / dt; + } + + // loop shape functions + for(size_t k = 0; k < scvf.num_sh(); ++k) + { + // Diffusion part + number sumVel = vViscoPerDiffLenSq[ip] * scvf.shape(k); + + // Convective term (no convective terms in the Stokes eq.) + if (! bStokes) + { + sumVel += vNormStdVelPerConvLen[ip] * upwind_shape_sh(ip, k); + + sumVel += vNormStdVelPerDownLen[ip] * + (downwind_shape_sh(ip, k) - upwind_shape_sh(ip, k)); + } + + for(int d2 = 0; d2 < dim; ++d2) + { + if(d2 == d) continue; + + sumVel -= vStdVel[ip][d2] * (scvf.global_grad(k))[d2]; + } + + // Add to rhs + rhs += sumVel * vCornerValue(d, k); + + // set stab shape + stab_shape_vel(ip, d, d, k) = sumVel / diag; + + for(int d2 = 0; d2 < dim; ++d2) + { + if(d2 == d) continue; + + const number sumVel2 = vStdVel[ip][d] * (scvf.global_grad(k))[d2]; + + rhs += sumVel2 * vCornerValue(d2, k); + + stab_shape_vel(ip, d, d2, k) = sumVel2 / diag; + } + + // Pressure part + const number sumP = -1.0 * (scvf.global_grad(k))[d] / density[ip]; + + // Add to rhs + rhs += sumP * vCornerValue(_P_, k); + + // set stab shape + stab_shape_p(ip, d, k) = sumP / diag; + } + + // Finally, the can invert this row + stab_vel(ip)[d] = rhs / diag; + } + } + } + /// need to solve system + else + { + UG_THROW("in stabilisation.h: FLOW::update(): Stop! this case is not implemented for DimFV1FTGeometry!\n"); + + // For the FLOW stabilization, there is no connection between the + // velocity components. Thus we can solve a system of size=numIP for + // each component of the velocity separately. This results in smaller + // matrices, that we have to invert. + + // First, we have to assemble the Matrix, that includes all connections + // between the ip velocity component. Note, that in this case the + // matrix is non-diagonal and we must invert it. + // The Matrix is the same for all dim-components. Thus we invert it only + // once. + + // size of the system + static const size_t N = maxNumIp; + + // a fixed size matrix + DenseMatrix< FixedArray2 > mat; + + // reset all values of the matrix to zero + mat = 0.0; + + // Loop integration points + for(size_t ip = 0; ip < numIp; ++ip) + { + // Time part + if(pvCornerValueOldTime != NULL) + mat(ip, ip) += 1./dt; + + // Diffusion part + mat(ip, ip) += vViscoPerDiffLenSq[ip]; + + // Convective Term (standard) + mat(ip, ip) += vNormStdVelPerConvLen[ip]; + + for(size_t ip2 = 0; ip2 < numIp; ++ip2) + { + // Convective Term by upwind + mat(ip, ip2) -= upwind_shape_ip(ip, ip2) * vNormStdVelPerConvLen[ip]; + + // correction of divergence error + mat(ip,ip2) += vNormStdVelPerDownLen[ip] * + (upwind_shape_ip(ip, ip2) - downwind_shape_ip(ip, ip2)); + } + } + + // we now create a matrix, where we store the inverse matrix + typename block_traits > >::inverse_type inv; + + // get the inverse + if(!GetInverse(inv, mat)) + UG_THROW("Could not compute inverse."); + + + // create vectors + DenseVector< FixedArray1 > contVel[dim][maxNumSh]; + DenseVector< FixedArray1 > contP[maxNumSh]; + DenseVector< FixedArray1 > xP; + DenseVector< FixedArray1 > xVel; + + // Now, we can create several vector that describes the contribution of the + // corner velocities. For each of this contribution + // components, we will apply the inverted matrix to get the stab_shapes + + // Loop integration points + for(int d = 0; d < dim; ++d) + { + for(size_t ip = 0; ip < numIp; ++ip) + { + // get SubControlVolumeFace + const typename TFVGeom::SCVF& scvf = geo->scvf(ip); + + // loop shape functions + for(size_t k = 0; k < numSh; ++k) + { + // Pressure part + contP[k][ip] = -1.0 * (scvf.global_grad(k))[d] / density[ip]; + + // Diffusion part + contVel[d][k][ip] = vViscoPerDiffLenSq[ip] * scvf.shape(k); + + // Convection part + contVel[d][k][ip] += vNormStdVelPerConvLen[ip] * upwind_shape_sh(ip, k); + + // terms for correction of divergence error + contVel[d][k][ip] += vNormStdVelPerDownLen[ip] * + (downwind_shape_sh(ip, k) - upwind_shape_sh(ip, k)); + + + for(int d2 = 0; d2 < dim; ++d2) + { + if(d2 == d) continue; + + contVel[d][k][ip] -= vStdVel[ip][d2] + * (scvf.global_grad(k))[d2]; + + contVel[d2][k][ip] = vStdVel[ip][d] + * (scvf.global_grad(k))[d2]; + } + } + } // end ip + + // compute all stab_shapes + for(size_t k = 0; k < numSh; ++k) + { + // apply for pressure stab_shape + MatMult(xP, 1.0, inv, contP[k]); + + // write stab_shape for pressure + //\todo: can we optimize this, e.g. without copy? + for(size_t ip = 0; ip < numIp; ++ip) + stab_shape_p(ip, d, k) = xP[ip]; + + // compute vel stab_shapes + for(int d2 = 0; d2 < dim; ++d2) + { + // apply for vel stab_shape + MatMult(xVel, 1.0, inv, contVel[d2][k]); + + // write stab_shape for vel + //\todo: can we optimize this, e.g. without copy? + for(size_t ip = 0; ip < numIp; ++ip) + stab_shape_vel(ip, d, d2, k) = xVel[ip]; + } + } + + // Finally, we can compute the values of the stabilized velocity for each + // integration point + + // vector of all contributions + DenseVector< FixedArray1 > f; + + // sum up all contributions of vel and p for rhs. + f = 0.0; + for(size_t k = 0; k < numSh; ++k) + { + // add velocity contribution + for(int d2 = 0; d2 < dim; ++d2) + VecScaleAdd(f, 1.0, f, vCornerValue(d2, k), contVel[d2][k]); + + // add pressure contribution + VecScaleAdd(f, 1.0, f, vCornerValue(_P_, k), contP[k]); + } + + // Loop integration points + for(size_t ip = 0; ip < numIp; ++ip) + { + // get SubControlVolumeFace + const typename TFVGeom::SCVF& scvf = geo->scvf(ip); + + // Source + if(pSource != NULL) + f[ip] += (*pSource)[ip][d]; + + // Time + if(pvCornerValueOldTime != NULL) + { + // interpolate old time step + // \todo: Is this ok? Or do we need the old stabilized vel ? + number oldIPVel = 0.0; + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + oldIPVel += scvf.shape(sh) * (*pvCornerValueOldTime)(d, sh); + + // add to rhs + f[ip] += oldIPVel / dt; + } + } + + // invert the system for all contributions + DenseVector< FixedArray1 > x; + MatMult(x, 1.0, inv, f); + + // write values in data structure + //\todo: can we optimize this, e.g. without copy? + for(size_t ip = 0; ip < numIp; ++ip) + { + // write stab_shape for vel + stab_vel(ip)[d] = x[ip]; + } + } // end dim + + } // end switch for non-diag +} + template <> void NavierStokesFLOWStabilization<1>::register_func() diff --git a/incompressible/fv1/stabilization.h b/incompressible/fv1/stabilization.h index 2086600..8444123 100644 --- a/incompressible/fv1/stabilization.h +++ b/incompressible/fv1/stabilization.h @@ -39,6 +39,7 @@ #include "../../upwind_interface.h" #include "lib_disc/spatial_disc/disc_util/fv1_geom.h" +#include "lib_disc/spatial_disc/disc_util/fv1FT_geom.h" #include "lib_disc/spatial_disc/user_data/data_import.h" @@ -111,11 +112,21 @@ class INavierStokesFV1Stabilization UG_THROW("No update function registered for Geometry "<::get(); - m_numScvf = geo.num_scvf(); - m_numSh = geo.num_sh(); + + // set sizes + if (TFVGeom::staticLocalData) + { + TFVGeom& geo = GeomProvider::get(); + m_numScvf = geo.num_scvf(); + m_numSh = geo.num_sh(); + } + else + { + // hard code as !maxNum, since maybe crash, e.g. in update() for computation of mat!! + m_numScvf = TFVGeom::maxNumSCVF; // changed on march 2019! before it was: dim+2; // TFVGeom::maxNumSCVF; + m_numSh = TFVGeom::maxNSH;; // changed on march 2019! before it was: dim+2; // TFVGeom::maxNSH; + } + // set sizes in upwind if(m_spUpwind.valid()) m_spUpwind->template set_geometry_type(); } @@ -332,7 +343,7 @@ class INavierStokesSRFV1Stabilization /// diff length number diff_length_sq_inv(size_t scvf) const { - UG_NSSTAB_ASSERT(scvf < this_type::num_ip(), "Invalid index."); + //UG_NSSTAB_ASSERT(scvf < this_type::num_ip(), "Invalid index."); return m_vDiffLengthSqInv[scvf]; } @@ -476,12 +487,24 @@ class NavierStokesFIELDSStabilization const DataImport, dim>* pSource, const LocalVector* pvCornerValueOldTime, number dt); + /// update of values for DimFV1FTGeometry + template + void update(const DimFV1FTGeometry >* geo, + const LocalVector& vCornerValue, + const MathVector vStdVel[], + const bool bStokes, + const DataImport& kinVisco, + const DataImport& density, + const DataImport, dim>* pSource, + const LocalVector* pvCornerValueOldTime, number dt); + private: void register_func(); template void register_func() { + { typedef FV1Geometry TGeom; typedef void (this_type::*TFunc)(const TGeom* geo, const LocalVector& vCornerValue, @@ -492,7 +515,23 @@ class NavierStokesFIELDSStabilization const DataImport, dim>* pSource, const LocalVector* pvCornerValueOldTime, number dt); + + this->template register_update_func(&this_type::template update); + } + { + typedef DimFV1FTGeometry > TGeom; + typedef void (this_type::*TFunc)(const TGeom* geo, + const LocalVector& vCornerValue, + const MathVector vStdVel[], + const bool bStokes, + const DataImport& kinVisco, + const DataImport& density, + const DataImport, dim>* pSource, + const LocalVector* pvCornerValueOldTime, number dt); + + this->template register_update_func(&this_type::template update); + } } }; @@ -557,13 +596,25 @@ class NavierStokesFLOWStabilization const DataImport& density, const DataImport, dim>* pSource, const LocalVector* pvCornerValueOldTime, number dt); - + + /// update of values for DimFV1FTGeometry + template + void update(const DimFV1FTGeometry >* geo, + const LocalVector& vCornerValue, + const MathVector vStdVel[], + const bool bStokes, + const DataImport& kinVisco, + const DataImport& density, + const DataImport, dim>* pSource, + const LocalVector* pvCornerValueOldTime, number dt); + private: void register_func(); template void register_func() { + { typedef FV1Geometry TGeom; typedef void (this_type::*TFunc)(const TGeom* geo, const LocalVector& vCornerValue, @@ -573,8 +624,22 @@ class NavierStokesFLOWStabilization const DataImport& density, const DataImport, dim>* pSource, const LocalVector* pvCornerValueOldTime, number dt); + + this->template register_update_func(&this_type::template update); + } + { + typedef DimFV1FTGeometry > TGeom; + typedef void (this_type::*TFunc)(const TGeom* geo, + const LocalVector& vCornerValue, + const MathVector vStdVel[], + const bool bStokes, + const DataImport& kinVisco, + const DataImport& density, + const DataImport, dim>* pSource, + const LocalVector* pvCornerValueOldTime, number dt); this->template register_update_func(&this_type::template update); + } } }; diff --git a/incompressible/fv1/two_phase_flow/interface_handler_2pf.h b/incompressible/fv1/two_phase_flow/interface_handler_2pf.h new file mode 100644 index 0000000..42779f2 --- /dev/null +++ b/incompressible/fv1/two_phase_flow/interface_handler_2pf.h @@ -0,0 +1,176 @@ +/* + * diffusion_interface_handler_local.h + * + * Created on: 19.01.2015 + * Author: suze + */ + +#ifndef INTERFACE_HANDLER_2PF_H_ +#define INTERFACE_HANDLER_2PF_H_ + +#include "lib_disc/spatial_disc/immersed_util/interface_handler/interface_handler_two_sided_cut/interface_handler_diffusion.h" + +namespace ug{ +namespace NavierStokes{ + + +template +class InterfaceHandlerLocal2PF : public InterfaceHandlerLocalDiffusion +{ + + public: + /// World dimension + static const int dim = TWorldDim; + + /// used boundary face type + typedef typename DimFV1CutGeometry >::BF interfaceBF; + + typedef typename domain_traits::grid_base_object grid_base_object; + + InterfaceHandlerLocal2PF(SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler, + number fluidDensity, number fluidKinVisc); + + virtual ~InterfaceHandlerLocal2PF() {} + + /////////////////////////////////////////////////////////////// + /// redefine base calss methods: + /////////////////////////////////////////////////////////////// + // bool update_elem(GridObject* elem, const MathVector* vCornerCoords, int interfaceOrientation); + + // int CollectCorners_FlatTop_2d(GridObject* elem); + + // size_t get_vertex_index(Vertex* vrt, GridObject* elem); + + + /////////////////////////////////////////////////////////////// + /// new methods: + /////////////////////////////////////////////////////////////// + + size_t num_particles() const { return this->m_spInterfaceProvider->num_particles();} + + /// get solution values + MathVector get_solution(size_t prtIndex, size_t timeSeriesInd) + { return this->m_spInterfaceProvider->get_solution(prtIndex, timeSeriesInd); } + + + number get_density() { return this->m_spInterfaceProvider->get_density(0); } + number get_density_fluid() { return m_fluidDensity; } + number get_kinVisc_fluid() { return m_fluidKinVisc; } + + const LocalIndices& get_local_indices() const { return m_ind; } + + void set_jacobian_tri(const LocalMatrix locJ) { m_locJ_tri = locJ; } + void set_jacobian_quad(const LocalMatrix locJ){ m_locJ_quad = locJ; } + + void set_defect_tri(const LocalVector locD) { m_locD_tri = locD; } + void set_defect_quad(const LocalVector locD){ m_locD_quad = locD; } + + void reset_defect_on_interface(LocalVector& locD, const size_t size); + + void reset_jacobian_on_interface(LocalMatrix& locJ, const size_t size); + + + void set_solution_tri(const LocalVector locU) { m_locU_tri = locU; } + void set_solution_quad(const LocalVector locU){ m_locU_quad = locU; } + + void set_DoF_tag_tri(const bool bFactor2_for_DoFIndex) + { m_shift_DoFIndex_tri = bFactor2_for_DoFIndex; return; } + void set_DoF_tag_quad(const bool bFactor2_for_DoFIndex) + { m_shift_DoFIndex_quad = bFactor2_for_DoFIndex; return; } + + const size_t get_index_shift_tri() const { return m_shift_DoFIndex_tri; } + const size_t get_index_shift_quad() const { return m_shift_DoFIndex_quad; } + + LocalMatrix& get_local_jacobian_tri() { return m_locJ_tri; } + LocalMatrix& get_local_jacobian_quad() { return m_locJ_quad; } + + LocalVector& get_local_defect_tri() { return m_locD_tri; } + LocalVector& get_local_defect_quad() { return m_locD_quad; } + + LocalVector& get_local_solution_tri() { return m_locU_tri; } + LocalVector& get_local_solution_quad() { return m_locU_quad; } + + void set_local_sol(LocalVector& solU, const size_t size, const LocalVector& lvec, const int orientation); + + LocalVector set_jump_values(LocalIndices ind, const size_t size); + LocalVector set_jump_grad_values(LocalIndices ind, const size_t size); + LocalVector set_source(const std::vector sourceIm, LocalIndices ind, const size_t size, const bool bElementIsCut) + {LocalVector dummy; return dummy;} + LocalVector set_source(LocalIndices ind, const size_t size, const bool bElementIsCut); + + double get_jump_value_const(const MathVector position); + double get_jump_value(const MathVector position); + double get_jump_value_ex3(const MathVector position); + double get_jump_grad_value(const MathVector position); + double get_jump_grad_value_ex3(const MathVector position); + + double get_source(const MathVector position); + double get_source_kappa(const MathVector position); + + // writes solution of global vector vec into this->m_verticesValue-array: + void write_solution(const std::vector verticesValues); + + + void resize_local_data(LocalVector locU) + { + LocalIndices ind = locU.get_indices(); + + for (size_t fct = 0; fct < (dim+1); ++fct) + { + // resize for cut triangle + ind.resize_dof(fct, 3); + m_locU_tri.resize(ind); + m_locD_tri.resize(ind); + m_locJ_tri.resize(ind); + } + for (size_t fct = 0; fct < (dim+1); ++fct) + { + // resize for cut quadrilateral + ind.resize_dof(fct, 4); + m_locU_quad.resize(ind); + m_locD_quad.resize(ind); + m_locJ_quad.resize(ind); + } + + UG_LOG("check LocalIndices ind:" << ind << "\n"); + + return; + } + + private: + + /// fuid parameter imported by Constructor() + number m_fluidDensity; + number m_fluidKinVisc; + + /// size of local algebra for flat top element: 'm_numFct' x 'm_numCo' + size_t m_numFct; + /// number of corners of flat top element + size_t m_numCo; + + /// new local algebra for resized flat top element + LocalIndices m_ind; + + // local data for assembling: + LocalMatrix m_locJ_tri; + LocalMatrix m_locJ_quad; + LocalVector m_locD_tri; + LocalVector m_locD_quad; + LocalVector m_locU_tri; + LocalVector m_locU_quad; + + // scale factor for access to DoFIndex on triangle or quadri as cut element + // --> for call during 'add_local_def/jac_to_global_interface()': + bool m_shift_DoFIndex_tri; + bool m_shift_DoFIndex_quad; + +}; + +}// namespace NavierStokes +} // end ug namespace + +#include "interface_handler_2pf_impl.h" + + +#endif /* INTERFACE_HANDLER_2PF_H_ */ diff --git a/incompressible/fv1/two_phase_flow/interface_handler_2pf_impl.h b/incompressible/fv1/two_phase_flow/interface_handler_2pf_impl.h new file mode 100644 index 0000000..be3bc53 --- /dev/null +++ b/incompressible/fv1/two_phase_flow/interface_handler_2pf_impl.h @@ -0,0 +1,566 @@ +/* + * diffusion_interface_handler_local_impl.h + * + * Created on: 15.01.2015 + * Author: suze + */ + +#ifndef INTERFACE_HANDLER_2PF_IMPL_ +#define INTERFACE_HANDLER_2PF_IMPL_ + +#include + +namespace ug{ +namespace NavierStokes{ + + +//hier methods aus moving_particle_impl.h einfuegen + +// call constructor of base class +template +InterfaceHandlerLocal2PF::InterfaceHandlerLocal2PF( + SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler, + number fluidDensity, number fluidKinVisc) : + InterfaceHandlerLocalDiffusion(interfaceProvider, cutElementHandler), + m_fluidDensity(fluidDensity), + m_fluidKinVisc(fluidKinVisc), + m_numFct(0), + m_numCo(0), + m_shift_DoFIndex_tri(false), + m_shift_DoFIndex_quad(false) +{ +} +; + +template +void InterfaceHandlerLocal2PF:: +write_solution(const std::vector verticesValues) +{ + this->m_verticesValue.clear(); + + for (size_t i = 0; i < verticesValues.size(); ++i) + this->m_verticesValue.push_back(verticesValues[i]); + + +// through error: + if ( this->m_verticesValue.size() != verticesValues.size() ) + { + UG_LOG("m_verticesValue.size(): " << this->m_verticesValue.size() << "\n"); + UG_LOG("verticesValues.size(): " << verticesValues.size() << "\n"); + UG_THROW("in InterfaceHandlerLocal2PF::write_solution: wrong size of m_verticesValue!\n"); + } + +} + +template +void InterfaceHandlerLocal2PF:: +reset_defect_on_interface(LocalVector& locD, const size_t size) +{ + if ( size > locD.num_all_dof(0) ) + { + UG_LOG("in 'reset_defect_on_interface()': size = " << size << ", locD.size = " << locD.num_all_dof(0) << "\n"); + UG_THROW("in 'reset_defect_on_interface()': size = " << size << ", locD.size = " << locD.num_all_dof(0) << " => claimed size is NOT equal to size of solution vector!\n"); + } +// loop and set solution in 'solU_tri': + for (size_t dof = 0; dof < locD.num_all_dof(0); ++dof) + { + // if dof_real is index of m_vertex: get solution from class: + if ( this->lies_onInterface_size(dof, size) ) + locD.value(0, dof) = 0.0; + } +} + +template +void InterfaceHandlerLocal2PF:: +reset_jacobian_on_interface(LocalMatrix& locJ, const size_t size) +{ + + if ( size > locJ.num_all_row_dof(0) ) + { + UG_LOG("in 'reset_jacobian_on_interface()': size = " << size << ", locJ.size = " << locJ.num_all_row_dof(0) << "\n"); + UG_THROW("in 'reset_jacobian_on_interface()': size = " << size << ", locJ.size = " << locJ.num_all_row_dof(0) << " => claimed size is NOT equal to size of solution vector!\n"); + } +// loop and set solution in 'solU_tri': + for (size_t dof1 = 0; dof1 < locJ.num_all_row_dof(0); ++dof1) + { + if ( this->lies_onInterface_size(dof1, size) ) + { + // erase all col-values of chosen row dof1: + for (size_t dof2 = 0; dof2 < locJ.num_all_col_dof(0); ++dof2) + locJ.value(0, dof1, 0, dof2) = 0.0; + } + + } + +} + +template +double InterfaceHandlerLocal2PF:: +get_jump_value(const MathVector position) +{ + return 0.0; + + double absValue = position[0]*position[0] + position[1]* position[1]; + double sum = position[0] + position[1]; + + double returnValue = log(absValue) - sin(sum); + + return returnValue; +} + +template +double InterfaceHandlerLocal2PF:: +get_jump_value_ex3(const MathVector position) +{ + + //return 0.0; + + if ( this->get_orientation() == 1) + return 0.0; + + double absValue = position[0]*position[0] + position[1]* position[1]; + double returnValue = exp(-absValue); + + return returnValue; +} + +template +double InterfaceHandlerLocal2PF:: +get_jump_value_const(const MathVector position) +{ + return 0.0; + + double absValue = position[0]*position[0] + position[1]* position[1]; + double factor = 8*(2*absValue - position[0] - position[1]); + + return factor*exp(-absValue); + + double sum = position[0] + position[1]; + + double returnValue = log(absValue) - sin(sum); + + return returnValue; +} + +template +double InterfaceHandlerLocal2PF:: +get_jump_grad_value_ex3(const MathVector position) +{ + //return 0.0; + + if ( this->get_orientation() == -1) + return 0.0; + + double absValue = position[0]*position[0] + position[1]* position[1]; + double sum = position[0] + position[1]; + + double returnValue = 8*(2*absValue - sum)*exp(-absValue); + + return returnValue; +} + +template +double InterfaceHandlerLocal2PF:: +get_jump_grad_value(const MathVector position) +{ + if ( this->get_orientation() == 1) + return 2.0; + else + return 0.0; + + double absValue = position[0]*position[0] + position[1]* position[1]; + + return -exp(-absValue); + + double sum = position[0] + position[1]; + MathVector normal; + normal[0] = position[0]; + normal[1] = position[1]; + + double returnValue = 2*(sin(sum) + 2)*(position[0]*normal[0] + position[1]*normal[1])/absValue; + returnValue -= cos(sum)*(cos(sum)+2)*(normal[0] + normal[1]); + + return returnValue; +} + + + +template +double InterfaceHandlerLocal2PF:: +get_source_kappa(const MathVector position) +{ + if ( this->get_orientation() == 1) + { + return 16.0*16.0; + } + else + { + if ( this->get_orientation() != -1) + UG_THROW("wrong orientation!\n"); + + double dist_x = position[0] - 0.1; + double dist_y = position[1] - 0.2; + double dist = sqrt(dist_x*dist_x+dist_y*dist_y); + + return 200*16*dist*dist; + + } + +} + +template +double InterfaceHandlerLocal2PF:: +get_source(const MathVector position) +{ + double absValue = position[0]*position[0] + position[1]* position[1]; + double sum = position[0] + position[1]; +// double dist = sqrt(absValue); + + double returnValue = 0.0; + if ( this->get_orientation() == 1) + returnValue = 2*sum*cos(sum)/absValue; + else + { + returnValue = -4*sin(sum)*(cos(sum)+1); + + if ( this->get_orientation() != -1) + UG_THROW("wrong orientation!\n"); + } + return 2.0; //returnValue; +} + +template +LocalVector InterfaceHandlerLocal2PF:: +set_source(LocalIndices ind, const size_t size, const bool bElementIsCut) +{ + LocalVector source; + ind.resize_dof(0, size); + source.resize(ind); + +// loop and set solution in 'solU_tri': + for (size_t dof = 0; dof < source.num_all_dof(0); ++dof) + { +/* if ( dof > 2 ) + source.value(0, dof) = sourceIm[2]; // done during 'add_def_elem_local()' + else + source.value(0, dof) = sourceIm[dof]; // done during 'add_def_elem_local()' +*/ + + + // if dof_real is index of m_vertex: get solution from class: + if ( this->lies_onInterface_size(dof, size) ) + { + size_t dof_real = this->real_index_size(dof, size); + source.value(0, dof) = get_source_kappa(this->get_VerticesPos(dof_real)); + } + else + { +/* + size_t dof_orig = this->corner_orig(dof); + source.value(0, dof) = sourceIm[dof_orig]; // done during 'add_def_elem_local()' +*/ + // careful: this->corner() returns corner coords of new corners => use dof-Index, NOT dof_orig-Index?! + source.value(0, dof) = get_source_kappa(this->corner(dof)); + + } + + } + + return source; +} + + +template +LocalVector InterfaceHandlerLocal2PF:: +set_jump_values(LocalIndices ind, const size_t size) +{ + LocalVector jump; + ind.resize_dof(0, size); + jump.resize(ind); + +// loop and set solution in 'solU_tri': + for (size_t dof = 0; dof < jump.num_all_dof(0); ++dof) + { + + // if dof_real is index of m_vertex: get solution from class: + if ( this->lies_onInterface_size(dof, size) ) + { + size_t dof_real = this->real_index_size(dof, size); + jump.value(0, dof) = get_jump_value_ex3(this->get_VerticesPos(dof_real)); + } + else + { + jump.value(0, dof) = 0.0; + } + } + + return jump; +} + + +template +LocalVector InterfaceHandlerLocal2PF:: +set_jump_grad_values(LocalIndices ind, const size_t size) +{ + LocalVector jump_grad; + ind.resize_dof(0, size); + jump_grad.resize(ind); + +// loop and set solution in 'solU_tri': + for (size_t dof = 0; dof < jump_grad.num_all_dof(0); ++dof) + { + + // if dof_real is index of m_vertex: get solution from class: + if ( this->lies_onInterface_size(dof, size) ) + { + size_t dof_real = this->real_index_size(dof, size); + jump_grad.value(0, dof) = get_jump_grad_value_ex3(this->get_VerticesPos(dof_real)); + } + else + { + jump_grad.value(0, dof) = 0.0; + } + } + + return jump_grad; + +} + + +template +void InterfaceHandlerLocal2PF:: +set_local_sol(LocalVector& solU, const size_t size, const LocalVector& lvec, const int orientation) +{ + if ( size > solU.num_all_dof(0) ) + { + UG_LOG("in 'set_local_sol()': size = " << size << ", solU.size = " << solU.num_all_dof(0) << "\n"); + UG_THROW("in 'set_local_sol()': size = " << size << ", solU.size = " << solU.num_all_dof(0) << " => claimed size is NOT equal to size of solution vector!\n"); + } +// loop and set solution in 'solU_tri': + for(size_t fct=0; fct < solU.num_all_fct(); ++fct) + for (size_t dof = 0; dof < solU.num_all_dof(fct); ++dof) + { + size_t dof_real = this->real_index_size(dof, size); + + // if dof_real is index of m_vertex: get solution from class: + if ( this->lies_onInterface_size(dof, size) ) + { + solU.value(fct, dof) = this->get_sol(dof_real); + } + else + { + solU.value(fct, dof) = lvec.value(fct,dof_real); + } + } + +} + +/* +template +int InterfaceHandlerLocal2PF:: +CollectCorners_FlatTop_2d(GridObject* elem) +{ + ////////////////////////////////////////////// + // 1) fill vector with fluid corners: + ////////////////////////////////////////////// + + this->m_vCornerCoords.clear(); + this->m_vInterfaceID.clear(); + this->m_vOriginalCornerID.clear(); + +// buffer vectors for (cornerCoords, cornerIndex) + std::vector, size_t > > vOutsideCorners; + std::vector, size_t > > vInsideCorners; + std::vector, size_t > > vNearIntCorners; + +// collect all vertices of the element + std::vector vVertex; + CollectVertices(vVertex, *this->m_spMG, elem); + + bool isFTVertex = false; + for(size_t i = 0; i < vVertex.size(); ++i) + { + // remember boolian for check, weather there existe at least one vertex, which is FT! + isFTVertex = this->is_FTVertex(vVertex[i], i); + if ( isFTVertex ) + break; + } + + if ( !isFTVertex ) + UG_THROW("Error in 'CollectCorners_FlatTop_2d': no vertex is FTVertex: should be true for at least 1 vertex!\n"); + + // collect all edges of the element + std::vector vEdges; + CollectEdgesSorted(vEdges, *this->m_spMG, elem); + + // loop vertices + ////////////////////////////////////////////// + // REMARK: + // order is the same as in 'vCornerCoords', therefore we can be sure, that the + // order of the new 'vCornerIBCoords' will be consistent with the grid standard + ////////////////////////////////////////////// + + bool bNearInterface = false; + for(size_t i = 0; i < vVertex.size(); ++i) + { + Vertex* vrtRoot = vVertex[i]; + + ////////////////////////////////////////////// + // case 1: + // vertex insideDomain + if ( !this->is_FTVertex(vrtRoot, i) ) + { + if ( this->is_nearInterfaceVertex(vrtRoot, i) ) + UG_THROW("NearInterface BUT !is_FT => neuerdings Fehler!!....\n"); + + this->m_vCornerCoords.push_back(this->m_aaPos[vrtRoot]); + this->m_vOriginalCornerID.push_back(i); + + vInsideCorners.push_back(std::make_pair(this->m_aaPos[vrtRoot], i)); + } + ////////////////////////////////////////////// + // case 2: + // vertex = FT + ON interface + // => KEINE Berechnung von 'intersectionPoint' notwendig! -> pushen und alten index pushen + + // REMARK: is_nearInterfaceVerx = false per default, if m_vThresholdOnLevel = 0.0 + else if ( this->is_nearInterfaceVertex(vrtRoot, i) ) + { + bNearInterface = true; + this->m_vCornerCoords.push_back(this->m_aaPos[vrtRoot]); + this->m_vOriginalCornerID.push_back(i); + this->m_vInterfaceID.push_back(this->m_vCornerCoords.size()-1); // attention: push AFTER 'm_vCornerCoords.push_back()'!! + + vOutsideCorners.push_back(std::make_pair(this->m_aaPos[vrtRoot], i)); + vNearIntCorners.push_back(std::make_pair(this->m_aaPos[vrtRoot], i)); + + } + ////////////////////////////////////////////// + // case 3: + // vertex 'outsideFluid' + // => NEUE Position berechen+pushen und alten index pushen + else + { + ////////////////////////////////////////////////////////////////////////////////////////// + // loop alle edges, die interface schneiden und damit einen neuen intersectionPnt + // beitragen zum damit assoziierten alten index + for(size_t e = 0; e < vEdges.size(); ++e) + { + Edge* edge = vEdges[e]; + std::vector vVertexEdge; + CollectVertices(vVertexEdge, *this->m_spMG, edge); + if ( vVertexEdge.size() != 2 ) + UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); + + Vertex* vrt1 = vVertexEdge[0]; + Vertex* vrt2 = vVertexEdge[1]; + size_t vrtInd1 = get_vertex_index(vrt1, elem); + size_t vrtInd2 = get_vertex_index(vrt2, elem); + + MathVector intersectionPnt; + + /////////////////////////////////////////////////////////////////// + // lies vrtRoot on a cutted edge? + /////////////////////////////////////////////////////////////////// + // case1: vrtRoot is intersectionPnt with insideCorner = near_interface_corner => remove! + if ( this->is_nearInterfaceVertex(vrt2, vrtInd2) || this->is_nearInterfaceVertex(vrt1, vrtInd1) ) + { bNearInterface = true; continue; } + // case2: vert2 = outsideParticle && vrt1 = insideParticle: + else if ( vrtRoot == vrt1 && !this->is_FTVertex(vrt2, vrtInd2) ){ + this->get_intersection_point(intersectionPnt, vrt2, vrt1); + } + // case3: vrt1 = outsideParticle && vrt2 = insideParticle: + else if ( vrtRoot == vrt2 && !this->is_FTVertex(vrt1, vrtInd1) ) + this->get_intersection_point(intersectionPnt, vrt1, vrt2); + else + continue; + + // check for correct inersectionPnt + if ( fabs(this->get_LSvalue_byPosition(intersectionPnt)) > 1e-6 ) + UG_THROW("in 'CollectIBCorners2d()': Error in computation of 'intersectionPnt':\n " + " intersectionPnt = " << intersectionPnt << "\n distance from interace = " << fabs(get_LSvalue_byPosition(intersectionPnt)) << "\n"); + + /////////////////////////////////////////////////////////////////// + // only push_back, if not included yet! + // -> can be ONLY the case, if the intersectionPoint is a node + if ( ! this->isIncluded(this->m_vCornerCoords, intersectionPnt) ) + { + + this->m_vCornerCoords.push_back(intersectionPnt); + this->m_vOriginalCornerID.push_back(i); + this->m_vInterfaceID.push_back(this->m_vCornerCoords.size()-1); // attention: push AFTER 'm_vCornerCoords.push_back()'!! + + vOutsideCorners.push_back(std::make_pair(intersectionPnt, i)); + } + + + } // end edge-loop + + } // end else-case + + } // end vrt-loop + +//////////////////////////////////////////////////////////////////////////////////////////// +// Postprecessing for quadrilaterals ( <=> vOutsideCorners == 2 ) +// (vInsideCorners.size() == 2) && (bNearInterface) => ALL nodes insideFluid, BUT one ON surface +// => no Quadrilateral, but Triangle!! +//////////////////////////////////////////////////////////////////////////////////////////// + MathVector normalDir(0.0); + if ( (this->m_vCornerCoords.size() == 4) && (!bNearInterface) && (dim == 2) ) + this->ResortQuadrilateral(vInsideCorners, vOutsideCorners, normalDir); + else if ( bNearInterface ) + { + // Quadrilateral -> Triangle + if ( vInsideCorners.size() == 1 ) // case 1 + { + // do nothing, since re-sorting not necessary...??? + } + // skip whole element, since only FT points are included + else if ( vInsideCorners.size() == 0 ) + UG_THROW("in 'CollectCorners_FlatTop_2d()': vInsideCorners.size() " + "= " << vInsideCorners.size() << "not possible!\n"); + } + + + return this->m_vCornerCoords.size(); + +} + + +// called by geo.update()!! +template +bool InterfaceHandlerLocal2PF:: +update_elem(GridObject* elem, const MathVector* vCornerCoords, int interfaceOrientation) +{ + bool do_update_local = false; + this->m_vBF.clear(); + +// computing flat top modus + this->m_elemModus = compute_element_modus(elem, interfaceOrientation); + + switch(this->m_elemModus) + { + case INSIDE_DOM: if ( dim == 2 ) this->set_flat_top_data(elem, vCornerCoords, ROID_TRIANGLE); + if ( dim == 3 ) this->set_flat_top_data(elem, vCornerCoords, ROID_TETRAHEDRON); + break; // usual assembling + case OUTSIDE_DOM: if ( dim == 2 ) this->set_flat_top_data(elem, vCornerCoords, ROID_TRIANGLE); + if ( dim == 3 ) this->set_flat_top_data(elem, vCornerCoords, ROID_TETRAHEDRON); + break; // usual assembling + case CUT_BY_INTERFACE: this->compute_flat_top_data(elem); + //if ( m_roid == ROID_PYRAMID )UG_THROW("PYRAMID\n"); + do_update_local = true; + break; // flat top assembling + default: + throw(UGError("Error in InterfaceHandlerLocalDiffusion::update(): switch(m_elemModus)!")); + } + + return do_update_local; + +} +*/ + +} // namespace NavierStokes +} // end ug namespace + +#endif /* INTERFACE_HANDLER_2PF_IMPL_ */ diff --git a/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf.h b/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf.h new file mode 100644 index 0000000..4f8dc0d --- /dev/null +++ b/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf.h @@ -0,0 +1,127 @@ +/* + * diffusion_interface_handler_local.h + * + * Created on: 19.01.2015 + * Author: suze + */ + +#ifndef MAPPER_2PF_H_ +#define MAPPER_2PF_H_ + +#include "lib_disc/spatial_disc/immersed_util/interface_handler/interface_handler_base.h" + +namespace ug{ +namespace NavierStokes{ + + +template +class InterfaceMapper2PF : public IInterfaceMapper +{ + + public: + /// World dimension + static const int dim = TDomain::dim; + /// Algebra type + typedef TAlgebra algebra_type; + + /// Type of algebra matrix + typedef typename algebra_type::matrix_type matrix_type; + + /// Type of algebra vector + typedef typename algebra_type::vector_type vector_type; + + /// Type of geometric base object + typedef typename domain_traits::grid_base_object grid_base_object; + + InterfaceMapper2PF(){}; + + InterfaceMapper2PF(SmartPtr > localHandler) + : m_spInterfaceHandlerLocal(localHandler), + m_numDoFs(0), + m_resized(false), + m_resized_defect(false), + m_scaleDoFs(false) + {} + + virtual ~InterfaceMapper2PF() {} + + + /// send local entries to global rhs + void add_local_vec_to_global(vector_type& vec, const LocalVector& lvec, + ConstSmartPtr dd); + void add_local_vec_to_global_interface(vector_type& vec, const LocalVector& lvec, + ConstSmartPtr dd); + + /// send local entries to global matrix + void add_local_mat_to_global(matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd); + void add_local_mat_to_global_interface(matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd); + + void adjust_mat_global(matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd){}; + + /// modifies local solution vector for adapted defect computation + void modify_LocalData(LocalMatrix& locJ, LocalVector& locU, + ConstSmartPtr dd){}; + void modify_LocalData(LocalVectorTimeSeries& uT, LocalMatrix& locJ, LocalVector& locU, + ConstSmartPtr dd){}; + + void modify_LocalData(LocalVector& locD, LocalVector& tmpLocD, LocalVector& locU, + ConstSmartPtr dd){}; + void modify_LocalData(LocalVectorTimeSeries& uT, LocalVector& locD, LocalVector& tmpLocD, LocalVector& locU, + ConstSmartPtr dd, size_t t){}; + + /// modifies global solution vector for adapted defect computation + void modify_GlobalSol(vector_type& vecMod, const vector_type& vec, + ConstSmartPtr dd); + + void modify_GlobalSol(SmartPtr > vSolMod, + ConstSmartPtr > vSol, + ConstSmartPtr dd){}; + + /////////////////////////////////////////////////////////////// + /// new methods: + /////////////////////////////////////////////////////////////// + void set_identity_mat_constraint(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd); + + LocalMatrix& get_local_jacobian_tri() + { return m_spInterfaceHandlerLocal->get_local_jacobian_tri(); } + LocalMatrix& get_local_jacobian_quad() + { return m_spInterfaceHandlerLocal->get_local_jacobian_quad(); } + + LocalVector& get_local_defect_tri() + { return m_spInterfaceHandlerLocal->get_local_defect_tri(); } + LocalVector& get_local_defect_quad() + { return m_spInterfaceHandlerLocal->get_local_defect_quad(); } + + void write_solution(const std::vector verticesValues) + { m_spInterfaceHandlerLocal->write_solution(verticesValues); } + + // called during init() of diffusionInterface: + void set_numDoFs(const size_t numDoFs) + { m_numDoFs = numDoFs;} + void set_numNewDoFs(const size_t numNewDoFs) + { m_numNewDoFs = numNewDoFs;} + + void set_bScaleDoFs(bool bScaleDoF) { m_scaleDoFs = bScaleDoF; } + + private: + SmartPtr > m_spInterfaceHandlerLocal; + // number of DoFs in global matrix + size_t m_numDoFs; + size_t m_numNewDoFs; + bool m_resized; + bool m_resized_defect; + bool m_scaleDoFs; + + +}; + +}// namespace NavierStokes +} // end ug namespace + +#include "loc_to_glob_mapper_2pf_impl.h" + + +#endif /* MAPPER_2PF_H_ */ diff --git a/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf_impl.h b/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf_impl.h new file mode 100644 index 0000000..d3d4050 --- /dev/null +++ b/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf_impl.h @@ -0,0 +1,386 @@ +/* + * diffusion_interface_handler_local_impl.h + * + * Created on: 15.01.2015 + * Author: suze + */ + +#ifndef MAPPER_2PF_IMPL_ +#define MAPPER_2PF_IMPL_ + + +namespace ug{ +namespace NavierStokes{ + + +template +void InterfaceMapper2PF:: +set_identity_mat_constraint(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd) +{ + DoFIndex index; + + for (size_t i = 0; i < 18; ++i) + { + index = DoFIndex(85 + i,0); + + BlockRef(mat(index, index), 0, 0) = 1.0; + } + +} + + + +template +void InterfaceMapper2PF:: +modify_GlobalSol(vector_type& vecMod, const vector_type& vec, ConstSmartPtr dd) +{ + + size_t numDoFs = vecMod.size(); + const size_t numNewDoFs = numDoFs - m_numDoFs; + + UG_LOG("---------------modify_GlobalSol--------------\n"); + UG_LOG(" vecMod.size(): " << numDoFs << "\n"); + UG_LOG(" vec.size(): " << vec.size() << "\n"); + UG_LOG("m_numDoFs: " << m_numDoFs << "\n"); + UG_LOG(" computed numNewDoFs: " << numNewDoFs << "\n"); + UG_LOG(" m_numNewDoFs: " << m_numNewDoFs << "\n"); + + + DoFIndex index; + std::vector verticesValue; + verticesValue.clear(); + + // numNewDoFs enthaelt schon fact *fct! --> siehe MovingInterface2PF.init() + for (size_t i = 0; i < numNewDoFs; ++i) + { + index = DoFIndex(m_numDoFs + i, 0); + double value = DoFRef(vec, index); + + verticesValue.push_back(value); + } + + + UG_LOG(" computed numNewDoFs: " << numNewDoFs << "\n"); + UG_LOG("length of verticesValue should be " << numNewDoFs << " = " << numNewDoFs << "\n"); + + if ( numNewDoFs != verticesValue.size() ) + { + UG_LOG(" computed numNewDoFs: " << numNewDoFs << "\n"); + UG_THROW("length of verticesValue should be " << numNewDoFs << " = " << numNewDoFs << "\n"); + } + + // call InterfaceHandlerLocal-method: + // no not doing it! Done locally in add_def: locU_tri and locU_quad: + write_solution(verticesValue); + +} + +template +void InterfaceMapper2PF:: +add_local_mat_to_global(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd) +{ + bool print = false; + +// resize global matrix dynamically: + const size_t numDoFs = mat.num_rows(); + + if ( print ) UG_LOG("*** vorher: vec.size(): " << numDoFs << "\n"); + + size_t numAllDoFs = m_numDoFs + m_numNewDoFs; + if ( m_scaleDoFs ) + numAllDoFs = m_numDoFs + 2*m_numNewDoFs; + + const int diffDoFs = numAllDoFs - numDoFs; + +// resize global defect ONCE: + if ( diffDoFs > 0 ) + { + mat.resize_and_keep_values(numAllDoFs, numAllDoFs); + if ( print ) + { + UG_LOG("*** m_numDoFs: " << m_numDoFs << "\n"); + UG_LOG("*** m_numNewDoFs: " << m_numNewDoFs << "\n"); + UG_LOG("*** numAllDoFs: " << numAllDoFs << "\n"); + UG_LOG("*** nachher: mat.num_rows(): " << mat.num_rows() << "\n"); + } + } + else if ( diffDoFs == 0 ) + { if ( print ) UG_LOG("no resizing!\n");} + else if ( diffDoFs < 0 ) + { + if ( print ) UG_LOG("diffDoFs = " << diffDoFs << "\n"); + UG_THROW("error in add_local_mat_to_global: diffDofs < 0\n"); + } + + + ElementModus modus = m_spInterfaceHandlerLocal->elementModus(); + + switch(modus) + { + case OUTSIDE_DOM: + AddLocalMatrixToGlobal(mat, lmat); + break; + case INSIDE_DOM: + AddLocalMatrixToGlobal(mat, lmat); + break; + case CUT_BY_INTERFACE: + add_local_mat_to_global_interface(mat, lmat, dd); + break; + default: + throw(UGError("Error in IInterfaceMapper::add_local_mat_to_global()!")); + + } + +} + + +template +void InterfaceMapper2PF:: +add_local_vec_to_global(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd) +{ + bool print = false; + + const size_t numDoFs = vec.size(); + + if ( print ) UG_LOG("*** vorher: vec.size(): " << numDoFs << "\n"); + + size_t numAllDoFs = m_numDoFs + m_numNewDoFs; + if ( m_scaleDoFs ) + numAllDoFs = m_numDoFs + 2*m_numNewDoFs; + + const int diffDoFs = numAllDoFs - numDoFs; + +// resize global defect ONCE: + if ( diffDoFs > 0 ) + { + vec.resize(numAllDoFs, true); + vec.set(0.0); +/* + bool bJac = m_spInterfaceHandlerLocal->get_jac_bool(); + if ( !bJac ) + { + // vec.set(0.0); + m_spInterfaceHandlerLocal->set_jac_bool(true); + } +*/ + if ( print ) + { + UG_LOG("*** m_numDoFs: " << m_numDoFs << "\n"); + UG_LOG("*** m_numNewDoFs: " << m_numNewDoFs << "\n"); + UG_LOG("*** numAllDoFs: " << numAllDoFs << "\n"); + UG_LOG("*** nachher: vec.size(): " << vec.size() << "\n"); + } + } + else if ( diffDoFs == 0 ) + { if ( print ) UG_LOG("no resizing!\n");} + else if ( diffDoFs < 0 ) + { + if ( print ) UG_LOG("diffDoFs = " << diffDoFs << "\n"); + UG_THROW("error in add_local_vec_to_global: diffDofs < 0\n"); + } + + + ElementModus modus = m_spInterfaceHandlerLocal->elementModus(); + + switch(modus) + { + case OUTSIDE_DOM: + AddLocalVector(vec, lvec); + break; + case INSIDE_DOM: + AddLocalVector(vec, lvec); + break; + case CUT_BY_INTERFACE: + add_local_vec_to_global_interface(vec, lvec, dd); + break; + default: + throw(UGError("Error in IInterfaceMapper::add_local_vec_to_global()!")); + + } +} + +//get_real_index(dof): +// if dof NOT on interface: returns orig corner index +// if dof ON interface: returns index of m_vertex-array + +template +void InterfaceMapper2PF:: +add_local_mat_to_global_interface(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd) +{ + UG_LOG("------------------------ START InterfaceMapper2PF ------------------------\n"); + + const LocalIndices& rowInd = lmat.get_row_indices(); + const LocalIndices& colInd = lmat.get_col_indices(); + + DoFIndex indexRow, indexCol; + + /////////////////////////////////////////////////////////////// + /// FIRST: add loc to glob for locJ_tri: + /////////////////////////////////////////////////////////////// + const LocalMatrix& locJ_tri = get_local_jacobian_tri(); + const bool shift_global_index_tri = m_spInterfaceHandlerLocal->get_index_shift_tri(); + + size_t numAllDoFs = m_numDoFs; + + if ( shift_global_index_tri ) + numAllDoFs = m_numDoFs + m_numNewDoFs; + +// UG_LOG("in InterfaceMapper2PF::add_loc_mat(): locJ_tri = " << locJ_tri << "\n"); + + for(size_t fct1=0; fct1 < locJ_tri.num_all_row_fct(); ++fct1) + for (size_t dof1 = 0; dof1 < locJ_tri.num_all_row_dof(fct1); ++dof1) + { + const size_t dof1_real = m_spInterfaceHandlerLocal->real_index_tri(dof1); + + // if dof1_real is index of m_vertex: compute global index: + if ( m_spInterfaceHandlerLocal->lies_onInterface_tri(dof1) ) + indexRow = DoFIndex(numAllDoFs + dof1_real, fct1); + else + indexRow = DoFIndex(rowInd.index(fct1, dof1_real), rowInd.comp(fct1, dof1_real)); + + for(size_t fct2=0; fct2 < locJ_tri.num_all_col_fct(); ++fct2) + for (size_t dof2 = 0; dof2 < locJ_tri.num_all_col_dof(fct2); ++dof2) + { + const size_t dof2_real = m_spInterfaceHandlerLocal->real_index_tri(dof2); + + // if dof1_real is index of m_vertex: compute global index: + if ( m_spInterfaceHandlerLocal->lies_onInterface_tri(dof2) ) + indexCol = DoFIndex(numAllDoFs + dof2_real, fct2); + else + indexCol = DoFIndex(colInd.index(fct2, dof2_real), colInd.comp(fct2, dof2_real)); + + // finally add loc to glob: + DoFRef(mat, indexRow, indexCol) += locJ_tri.value(fct1, dof1, fct2, dof2); + + if ( indexRow[0] == 0 || indexRow[0] == 30 ){ + UG_LOG("------------------------ tri: += " << locJ_tri.value(0, dof1, 0, dof2) << "\n"); + UG_LOG("(indexRow, indexCol) = " << indexRow[0] << "," << indexCol[0] << "\n"); + } + } + } + + /////////////////////////////////////////////////////////////// + /// SECOND: add loc to glob for locJ_tri: + /////////////////////////////////////////////////////////////// + const LocalMatrix& locJ_quad = get_local_jacobian_quad(); + const bool shift_global_index_quad = m_spInterfaceHandlerLocal->get_index_shift_quad(); + + // reset numAllDoFs! + numAllDoFs = m_numDoFs; + + if ( shift_global_index_quad ) + numAllDoFs = m_numDoFs + m_numNewDoFs; + +// UG_LOG("in InterfaceMapper2PF::add_loc_mat(): locJ_quad = " << locJ_quad << "\n"); + + for(size_t fct1=0; fct1 < locJ_quad.num_all_row_fct(); ++fct1) + for (size_t dof1 = 0; dof1 < locJ_quad.num_all_row_dof(fct1); ++dof1) + { + size_t dof1_real = m_spInterfaceHandlerLocal->real_index_quad(dof1); + + // if dof1_real is index of m_vertex: compute global index: + if ( m_spInterfaceHandlerLocal->lies_onInterface_quad(dof1) ) + indexRow = DoFIndex(numAllDoFs + dof1_real, fct1); + else + indexRow = DoFIndex(rowInd.index(fct1, dof1_real), rowInd.comp(fct1, dof1_real)); + + for(size_t fct2=0; fct2 < locJ_quad.num_all_col_fct(); ++fct2) + for (size_t dof2 = 0; dof2 < locJ_quad.num_all_col_dof(fct2); ++dof2) + { + size_t dof2_real = m_spInterfaceHandlerLocal->real_index_quad(dof2); + + // if dof1_real is index of m_vertex: compute global index: + if ( m_spInterfaceHandlerLocal->lies_onInterface_quad(dof2) ) + indexCol = DoFIndex(numAllDoFs + dof2_real, fct2); + else + indexCol = DoFIndex(colInd.index(fct2, dof2_real), colInd.comp(fct2, dof2_real)); + + // finally add loc to glob: + DoFRef(mat, indexRow, indexCol) += locJ_quad.value(fct1, dof1, fct2, dof2); + + if ( indexRow[0] == 0 || indexRow[0] == 30){ + UG_LOG("------------------------ quad: += " << locJ_quad.value(0, dof1, 0, dof2) << "\n"); + UG_LOG("(indexRow, indexCol) = " << indexRow[0] << "," << indexCol[0] << "\n"); + } + } + } + + UG_LOG("------------------------ END InterfaceMapper2PF ------------------------\n"); + +} + +template +void InterfaceMapper2PF:: +add_local_vec_to_global_interface(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd) +{ + DoFIndex index_print; + + const LocalIndices& ind = lvec.get_indices(); + DoFIndex index; + + /////////////////////////////////////////////////////////////// + /// FIRST: add loc to glob for locD_tri: + /////////////////////////////////////////////////////////////// + const LocalVector& locD_tri = get_local_defect_tri(); + const bool shift_global_index_tri = m_spInterfaceHandlerLocal->get_index_shift_tri(); + + size_t numAllDoFs = m_numDoFs; + + if ( shift_global_index_tri ) + { numAllDoFs = m_numDoFs + m_numNewDoFs; + UG_LOG("it is shifted!\n"); + } +// UG_LOG("in InterfaceMapper2PF::add_loc_vec(): locD_tri = " << locD_tri << "\n"); + + for(size_t fct=0; fct < locD_tri.num_all_fct(); ++fct) + for (size_t dof = 0; dof < locD_tri.num_all_dof(fct); ++dof) + { + const size_t dof_real = m_spInterfaceHandlerLocal->real_index_tri(dof); + + // if dof_real is index of m_vertex: compute global index: + if ( m_spInterfaceHandlerLocal->lies_onInterface_tri(dof) ) + index = DoFIndex(numAllDoFs + dof_real,fct); + else + index = DoFIndex(ind.index(fct, dof_real), ind.comp(fct, dof_real)); + + // finally add loc to glob: + DoFRef(vec, index) += locD_tri.value(fct, dof); + + } + + + /////////////////////////////////////////////////////////////// + /// SECOND: add loc to glob for locU_quad: + /////////////////////////////////////////////////////////////// + const LocalVector& locD_quad = get_local_defect_quad(); + const bool shift_global_index_quad = m_spInterfaceHandlerLocal->get_index_shift_quad(); + +// reset numAllDoFs! + numAllDoFs = m_numDoFs; + + if ( shift_global_index_quad ) + numAllDoFs = m_numDoFs + m_numNewDoFs; + +// UG_LOG("in InterfaceMapper2PF::add_loc_vec(): locD_quad = " << locD_quad << "\n"); + + for(size_t fct=0; fct < locD_quad.num_all_fct(); ++fct) + for (size_t dof = 0; dof < locD_quad.num_all_dof(0); ++dof) + { + size_t dof_real = m_spInterfaceHandlerLocal->real_index_quad(dof); + + // if dof_real is index of m_vertex: compute global index: + if ( m_spInterfaceHandlerLocal->lies_onInterface_quad(dof) ) + index = DoFIndex(numAllDoFs + dof_real,fct); + else + index = DoFIndex(ind.index(fct, dof_real), ind.comp(fct, dof_real)); + + // finally add loc to glob: + DoFRef(vec, index) += locD_quad.value(fct, dof); + } + +} + +} // namespace NavierStokes +} // end ug namespace + +#endif /* MAPPER_2PF_IMPL_ */ diff --git a/incompressible/fv1/two_phase_flow/two_phase_flow.h b/incompressible/fv1/two_phase_flow/two_phase_flow.h new file mode 100644 index 0000000..7c7b884 --- /dev/null +++ b/incompressible/fv1/two_phase_flow/two_phase_flow.h @@ -0,0 +1,216 @@ +/* + * diffusion_interface.h + * + * Created on: 24.08.2017 + * Author: suze + */ + +#ifndef PF2_INTERFACE_H_ +#define PF2_INTERFACE_H_ + + +#ifdef UG_PARALLEL + #include "lib_grid/parallelization/load_balancer_util.h" +#endif + +#include "../navier_stokes_fv1.h" +#include "../../../navier_stokes_base.h" +#include "interface_handler_2pf.h" +#include "loc_to_glob_mapper_2pf.h" +#include "lib_disc/spatial_disc/immersed_util/immersed_interface_base.h" + +namespace ug{ +namespace NavierStokes{ + + + +template < typename TDomain, typename TAlgebra> +class MovingInterface2PF + : public IMovingInterface +{ + public: + /// world Dimension + static const int dim = TDomain::dim; + + /// Algebra type + typedef TAlgebra algebra_type; + + /// Type of algebra matrix + typedef typename algebra_type::matrix_type matrix_type; + + /// Type of algebra vector + typedef typename algebra_type::vector_type vector_type; + + typedef typename domain_traits::grid_base_object grid_base_object; + + MovingInterface2PF( + SmartPtr > ass, + SmartPtr > spMaster, + SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler, + number fluidDensity1, number fluidDensity2); + + void set_StdFV_assembling(bool bValue) { m_spInterfaceHandlerLocal->set_StdFV_assembling(bValue);} + bool StdFV_assembling() { return m_spInterfaceHandlerLocal->StdFV_assembling(); } + + + // destructor + ~MovingInterface2PF(){}; + + /// called via .lua: + void initialize_threshold(TDomain& domain, const int baseLevel, const int topLevel); + void set_threshold(size_t level, const number threshold) + { m_spCutElementHandler->set_threshold(level, threshold); } + + ////////////////////////////////////////////////////////////////////////////////// + /// Info - 'initialize_interface()': + /// + /// computes vertices on intersection of cut element edges and interface: + /// for 2d: instead of computing intersections: count number of cut elements! + /// -> #cutElements == #m_vertices + /// -> called during init() + ////////////////////////////////////////////////////////////////////////////////// + + const size_t initialize_interface(vector_type& u, ConstSmartPtr dd); + + + number MeanElementDiameter(TDomain& domain, int level); + + ////////////////////////////////////////////////////////////////////////////////// + // ---> .lua: update(u, deltaT, u:grid_level()): update global indices (transInd...) + // => A. copy_solution(topLev) + // B. update(baseLev-topLev) + // C. update_solution(topLev) + ////////////////////////////////////////////////////////////////////////////////// + // write solution to nodes outside fluid with particle velocities + // --> call method vie .lua BEFORE 'solTimeSeries:push_discard_oldest(oldestSol, time)': + // => in case that outside nodes are inside AFTER update_prtCoords: NO solution defined here! + + + /// call of the method via lua to set the real velocity values within the particle domain + void adjust_global_solution(vector_type& u, const int topLevel); + void fill_particle_solution(vector_type& u, const int topLevel, const number time); + void update(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel, const number time) + { + int topLev = spApproxSpace->num_levels()-1; + if ( topLev != topLevel ) + UG_THROW("MovingParticle::update: parameter 'topLevel' = " << topLevel << " != " + << topLev << "current top leven! \n"); + + // fill particle nodes with their real solution + fill_particle_solution(u, topLevel, time); + + // update data: bool_marker + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + m_spCutElementHandler->template init(dd, baseLevel, topLevel); + + } + + void set_interface_values(vector_type& u, const int numDoFs, const int num_newDoFs) + { +// double value = 20.0*0.4*0.4*0.4*0.4; + DoFIndex index; + + for (size_t i = 0; i < num_newDoFs; ++i) + { + index = DoFIndex(numDoFs + i,0); + // DoFRef(u, index) = value; + } + } + void set_analytic_solution(vector_type& u, SmartPtr > spApproxSpace, SmartPtr mg, const int topLevel); + void adjust_for_error(vector_type& u, vector_type& uCopy, SmartPtr > spApproxSpace, SmartPtr mg, const int topLevel); + + double compute_solution_value(const MathVector& vrtPos); + + number get_integral() + { return m_spInterfaceHandlerLocal->get_integral(); } + + void init(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel, bool bScaleDoFs) + { + m_spApproxSpace = spApproxSpace; + + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + + size_t numDoFs = u.size(); + const size_t num_interfaceDoFs = initialize_interface(u, dd); + const size_t num_newDoFs = 4*num_interfaceDoFs; + + m_spInterfaceMapper->set_numDoFs(numDoFs); + m_spInterfaceMapper->set_numNewDoFs(num_interfaceDoFs); + + UG_LOG("________________ numDoFs = " << numDoFs << "\n"); + UG_LOG("________________ num_interfaceDoFs = " << num_interfaceDoFs << "\n"); + UG_LOG("________________ num_newDoFs = " << num_newDoFs << "\n"); + + // values for new DoFs are set to 0.0 by the 'resize()'-method (see vector.h): + if ( bScaleDoFs ) + u.resize(numDoFs + 2*num_newDoFs); + else + u.resize(numDoFs + num_newDoFs); + + UG_LOG("AGAIN: in init(): numALLDoFs = " << u.size() << "\n"); + + m_spInterfaceMapper->set_bScaleDoFs(bScaleDoFs); + m_spInterfaceHandlerLocal->set_bScaleDoFs(bScaleDoFs); + + m_spInterfaceHandlerLocal->init_integral(); + + // lieber in jedem Schritt ueber 'modify_GlobalSol()' (mapper!) setzten! + //set_interface_values(u, numDoFs, num_newDoFs); + + // not necessary anymore: only local evaluations within diffusion problem! + //m_spCutElementHandler->template init_marker(dd, baseLevel, topLevel); + } + + /// checks if grid data is updated and returns 'levIndex'-pair for 'gridLevel' in 'm_Map' + int get_Index(const GridLevel& gridLevel) + { + ConstSmartPtr dd = m_spApproxSpace->dof_distribution(gridLevel); + + const int levIndex = m_spCutElementHandler->get_Index(gridLevel, dd); + + return levIndex; + } + + //ToDo: method needed? + void update_interface( const int topLevel, number deltaT); + + bool is_time_dependent() { return m_spInterfaceHandlerLocal->is_time_dependent();} + + /// helper functions for compute_error_on_circle() + void interpolate_point(ConstSmartPtr dd, const vector_type& u, + const MathVector& evalPos, MathVector& interpolation); + void compute_error_on_circle(const vector_type& u, const int topLevel, number radius); + + void print_deltaP(const vector_type& u, const int topLevel); + void print_pressure(const vector_type& u, const int topLevel); + void print_pressure_nodal(const vector_type& u, const int topLevel); + + /// writing data to file; called via .lua + void print_velocity(const vector_type& u, const int topLevel, number time, const char* filename); + void print_velocity_many_particles(const vector_type& u, const int topLevel, number time, const char* filename); + + private: + /// current ApproxSpace + SmartPtr > m_spApproxSpace; + + SmartPtr > m_spInterfaceProvider; + SmartPtr > m_spCutElementHandler; + SmartPtr > m_spInterfaceHandlerLocal; + + SmartPtr > m_spInterfaceMapper; + +}; + +} // end namespace NavierStokes +} // end namespace ug + + +#include "two_phase_flow_impl.h" + +#endif /* PF2_INTERFACE_H_ */ + + + + diff --git a/incompressible/fv1/two_phase_flow/two_phase_flow_impl.h b/incompressible/fv1/two_phase_flow/two_phase_flow_impl.h new file mode 100644 index 0000000..abe7887 --- /dev/null +++ b/incompressible/fv1/two_phase_flow/two_phase_flow_impl.h @@ -0,0 +1,329 @@ + +/* + * moving_interface_diffusion_impl.h + * + * Created on: 24.08.2017 + * Author: suze + */ + +#ifndef PF2_INTERFACE_IMPL_ +#define PF2_INTERFACE_IMPL_ + + +namespace ug { +namespace NavierSTokes { + +/////////////////////////////////////////////////////////// +// Implementation of the methods class +// 'MovingInterface2PF' +/////////////////////////////////////////////////////////// + + +template +MovingInterface2PF::MovingInterface2PF( + SmartPtr > ass, + SmartPtr > spMaster, SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler, + number fluidDensity1, number fluidDensity2) : + m_spInterfaceProvider(interfaceProvider), + m_spInterfaceHandlerLocal(new InterfaceHandlerLocal2PF(interfaceProvider, cutElementHandler, fluidDensity1, fluidDensity2)), + m_spCutElementHandler(cutElementHandler), + m_spInterfaceMapper(new InterfaceMapper2PF (m_spInterfaceHandlerLocal)) +{ + if (interfaceProvider->num_particles() == 0) + UG_THROW("MovingParticle::Constructor(): no particles initializen in 'globalHandler\n"); + + // initialize singleton and set local handler + typedef DimFV1CutGeometry > TFVGeom; + TFVGeom& geo = GeomProvider::get(LFEID(LFEID::LAGRANGE, dim, 1),1); + geo.set_interface_handler(m_spInterfaceHandlerLocal); + + // initialize mapper within domainDisc: + SmartPtr > assAdapt = ass->ass_tuner(); + assAdapt->set_mapping(m_spInterfaceMapper.get()); + + assAdapt->enable_modify_solution(true); + // => assTuner->modify_LocSol() = mapper->modify_LocSol() + // see: ass_tuner.h: 114 + + +} + +template +double MovingInterface2PF:: +compute_solution_value(const MathVector& vrtPos) +{ + double kappa_1 = 1.0; + double kappa_2 = 10.0; + double sqR = 0.4*0.4; + double dist_x = vrtPos[0] - 0.1; + double dist_y = vrtPos[1] - 0.2; + double sqDist = dist_x*dist_x+dist_y*dist_y; + + double value = -4*kappa_1*kappa_2*kappa_2*sqR*sqDist + 2*sqR*sqR*kappa_2*(2*kappa_1*kappa_2 - 1); + + double dist = sqrt(sqDist); + if ( dist > 0.4 ) + { + value = -2*kappa_2*sqDist*sqDist; + UG_LOG("value = " << value << "\n"); + } + return value; +} + +template +void MovingInterface2PF:: +set_analytic_solution(vector_type& u, SmartPtr > spApproxSpace, SmartPtr mg, const int topLevel) +{ + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + typedef MathVector position_type; + typedef Attachment position_attachment_type; + typedef Grid::VertexAttachmentAccessor position_accessor_type; + + //SmartPtr m_spMG = mg.operator->(); + position_attachment_type m_aPos = GetDefaultPositionAttachment(); + position_accessor_type m_aaPos; + + if(!mg->has_attachment(m_aPos)) + mg->attach_to(m_aPos); + m_aaPos.access(*mg, m_aPos); + + typedef typename domain_traits::grid_base_object grid_base_object; + + typename DoFDistribution::traits::const_iterator iter, iterEnd; + iter = dd->template begin(); + iterEnd = dd->template end(); + + // loop elements in order to compute the volume and set rhs: + for( ; iter != iterEnd; iter++) + { + // get element + grid_base_object* elem = *iter; + std::vector > vCornerCoords; + CollectCornerCoordinates(vCornerCoords, *elem, m_aaPos); + + std::vector ind; + dd->dof_indices(elem, 0, ind); + + // loop vertices + for(size_t i = 0; i < elem->num_vertices(); ++i) + { + // get vertex +// Vertex* vrt = elem->vertex(i); + double value = compute_solution_value(vCornerCoords[i]); + DoFRef(u, ind[i]) = value; + } + } + +} + +template +void MovingInterface2PF:: +adjust_for_error(vector_type& u, vector_type& uCopy, SmartPtr > spApproxSpace, SmartPtr mg, const int topLevel) +{ + + + size_t numDoFs = u.size(); + UG_LOG("domain disc: numDoFs = " << numDoFs << "\n"); + size_t numDoFsCopy = uCopy.size(); + UG_LOG("domain disc: numDoFsCopy = " << numDoFsCopy << "\n"); + + u.resize(numDoFsCopy); + + numDoFs = u.size(); + UG_LOG("**domain disc: numDoFs = " << numDoFs << "\n"); + + + + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + + typedef MathVector position_type; + typedef Attachment position_attachment_type; + typedef Grid::VertexAttachmentAccessor position_accessor_type; + + //SmartPtr m_spMG = mg.operator->(); + position_attachment_type m_aPos = GetDefaultPositionAttachment(); + position_accessor_type m_aaPos; + + if(!mg->has_attachment(m_aPos)) + mg->attach_to(m_aPos); + m_aaPos.access(*mg, m_aPos); + + typedef typename domain_traits::grid_base_object grid_base_object; + + typename DoFDistribution::traits::const_iterator iter, iterEnd; + iter = dd->template begin(); + iterEnd = dd->template end(); + + // loop elements in order to compute the volume and set rhs: + for( ; iter != iterEnd; iter++) + { + // get element + grid_base_object* elem = *iter; + + ElementModus elemModus = m_spInterfaceHandlerLocal->compute_element_modus(elem, 1); + bool do_adjust = false; + + switch(elemModus) + { + case INSIDE_DOM: break; + case OUTSIDE_DOM: break; + + case CUT_BY_INTERFACE: do_adjust = true; break; + default: + throw(UGError("Error in InterfaceHandlerLocalDiffusion::update(): switch(m_elemModus)!")); + } + + + std::vector > vCornerCoords; + CollectCornerCoordinates(vCornerCoords, *elem, m_aaPos); + + std::vector ind; + dd->dof_indices(elem, 0, ind); + + // loop vertices + for(size_t i = 0; i < elem->num_vertices(); ++i) + { + // get vertex + // Vertex* vrt = elem->vertex(i); + + if (do_adjust) DoFRef(u, ind[i]) = 0.0; + } + + } + +} + +template +const size_t MovingInterface2PF:: +initialize_interface(vector_type& u, ConstSmartPtr dd) +{ + typedef typename domain_traits::grid_base_object grid_base_object; + + typename DoFDistribution::traits::const_iterator iter, iterEnd; + iter = dd->template begin(); + iterEnd = dd->template end(); + + size_t num_cutElements = 0; + + // loop elements in order to compute the volume and set rhs: + for( ; iter != iterEnd; iter++) + { + // get element + grid_base_object* elem = *iter; + + ElementModus elemModus = m_spCutElementHandler->compute_element_modus(elem, 1); + + if ( elemModus == CUT_BY_INTERFACE ) + num_cutElements += 1; + + } + + return num_cutElements; + +} + +template +number MovingInterface2PF:: +MeanElementDiameter(TDomain& domain, int level) +{ + typedef typename domain_traits::grid_base_object TElem; + typedef typename geometry_traits::iterator ListIter; + + ListIter iter = domain.grid()->template begin(level); + ListIter iterEnd = domain.grid()->template end(level); + + number mean = 0.0; + size_t numIter = 0; + for (; iter != iterEnd; ++iter) { + mean += ElementDiameterSq(*domain.grid(), domain.position_accessor(), + *iter); + numIter++; + } + + mean = mean / numIter; + +#ifdef UG_PARALLEL + // share value between all procs + pcl::ProcessCommunicator com; + // ToDO: PCL_RO_MIN oder MAX oder doch mean noch berechnen m.H.v. /numProcs??? + //UG_THROW("in MeanElementDiameter(): was macht 'allredue' im Parallelen???\n"); + mean = com.allreduce(mean, PCL_RO_MIN); +#endif + + UG_LOG("nach com.allreduce: mean = " << std::sqrt(mean) << "\n"); + return std::sqrt(mean); +} + +template +void MovingInterface2PF:: +initialize_threshold(TDomain& domain, const int baseLevel, const int topLevel) +{ + UG_LOG("----------------- START initialize_threshold() ---------------- \n"); + + if (baseLevel < 0) + UG_THROW( + "initialize_threshold(): no cast of baselevel from 'int' tp 'size_t' possible! \n"); + if (topLevel < 0) + UG_THROW( + "initialize_threshold(): no cast of toplevel from 'int' tp 'size_t' possible! \n"); + +// compute level-dependent value for threshold: + for (size_t lev = baseLevel; lev <= (size_t) topLevel; ++lev) { + const number maxLength = MaxElementDiameter(domain, lev); + const number meanLength = MeanElementDiameter(domain, lev); + UG_LOG("maxLength = " << maxLength << "\n"); + UG_LOG("meanLength = " << meanLength << "\n"); + UG_LOG("threshold_max = " << maxLength*maxLength << "\n"); + UG_LOG("threshold_mean = " << meanLength*meanLength << "\n"); + + set_threshold(lev, meanLength * meanLength); + } + + UG_LOG("----------------- END initialize_threshold() ---------------- \n"); + +} + +template +void MovingInterface2PF:: +update_interface( const int topLevel, number deltaT) +{ + if ( deltaT == 0.0 ) + UG_THROW("ParticleProvider:update_prtCoords: deltaT = " << deltaT << " => no update necessary!\n"); + +// get level index + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + UG_LOG("update_prtCoords() for levIndex = " << levIndex << "\n"); + UG_LOG("update_prtCoords() for deltaT = " << deltaT << "\n"); + +// update center + for (size_t p = 0; p < m_spInterfaceProvider->num_particles(); ++p) + { +#ifdef UG_PARALLEL + std::vector ElemList = m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; + std::vector ElemList = m_vvvElemListCut[levIndex][p]; + UG_LOG("1_ update_prtCoords() ElemList.size(): " << ElemList.size() << "\n"); + if ( ElemList.size() == 0 ) { + UG_LOG("2_ update_prtCoords() ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + continue; + } +#endif + + // get data: + MathVector centerNew = m_spInterfaceProvider->get_center(p); + number soution = m_spInterfaceProvider->get_solution(p, 0); + UG_LOG(" solution = " << soution << "\n"); + UG_LOG("deltaT = " << deltaT << "\n"); + +// ToDo: Hier das interface irgendwie updaten?? + + + } // end particle loop + +} + +} // end namespace NavierStokes +} // end namespace ug + +#endif /* PF2_INTERFACE_IMPL_ */ diff --git a/incompressible/incompressible_navier_stokes_plugin.cpp b/incompressible/incompressible_navier_stokes_plugin.cpp index 6a5ca30..68c5bc8 100644 --- a/incompressible/incompressible_navier_stokes_plugin.cpp +++ b/incompressible/incompressible_navier_stokes_plugin.cpp @@ -50,8 +50,7 @@ #include "fv/register_fv.h" #include "fvcr/register_fvcr.h" #include "fe/register_fe.h" - - +#include "particle_laden_flow_plugin.h" using namespace std; @@ -323,6 +322,8 @@ void Init___IncompressibleNavierStokes(Registry* reg, string grp) Init___NavierStokes___FVCR(reg, grp); Init___NavierStokes___FV(reg, grp); Init___NavierStokes___FE(reg, grp); + + Init___ParticleLadenFlow(reg, grp); } UG_REGISTRY_CATCH_THROW(grp); } diff --git a/incompressible/particle_laden_flow_plugin Kopie.cpp b/incompressible/particle_laden_flow_plugin Kopie.cpp new file mode 100644 index 0000000..963c229 --- /dev/null +++ b/incompressible/particle_laden_flow_plugin Kopie.cpp @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt + * Author: Sebastian Reiter + * + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#ifdef UG_PARALLEL + #include "../../Parmetis/src/unificator_interface.h" +#endif + +#include "bridge/util.h" +#include "bridge/util_domain_algebra_dependent.h" + +#include "common/log.h" +#include "lib_disc/function_spaces/grid_function.h" +#include "lib_disc/dof_manager/dof_distribution.h" +#include "fv1/navier_stokes_fv1.h" +#include "incompressible_navier_stokes_base.h" +#include "fv1/bnd/inflow_fv1.h" +#include "bnd/inflow_base.h" + + +#include "lib_disc/spatial_disc/local_to_global/local_to_global_mapper.h" +#include "fv1/immersed_interface_base/gmg_transfer/particle_transfer.h" +#include "fv1/moving_particle/interface_handler_particle.h" +#include "fv1/moving_particle/moving_particle.h" +#include "fv1/diffusion_interface/interface_handler_diffusion.h" +#include "fv1/diffusion_interface/diffusion_interface.h" +//#include "fv1/two_phase_flow/two_phase_flow.h" + + +using namespace std; +using namespace ug::bridge; + +namespace ug{ +namespace ParticleLadenFlow{ + +/** + * Class exporting the functionality of the plugin. All functionality that is to + * be used in scripts or visualization must be registered here. + */ +struct FunctionalityIncomp +{ + +/** + * Function called for the registration of Domain and Algebra dependent parts + * of the plugin. All Functions and Classes depending on both Domain and Algebra + * are to be placed here when registering. The method is called for all + * available Domain and Algebra types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void DomainAlgebra(Registry& reg, string grp) +{ + string suffix = GetDomainAlgebraSuffix(); + string tag = GetDomainAlgebraTag(); + + typedef ApproximationSpace approximation_space_type; + typedef GridFunction function_type; + +// IMovingInterfaceBase + { + typedef MovingInterfaceBase::IMovingInterface T; + string name = string("IMovingInterfaceBase").append(suffix); + reg.add_class_(name, grp); + reg.add_class_to_group(name, "IMovingInterfaceBase", tag); + + } +/* + // MovingInterface2PF + { + typedef MovingInterface2PF::MovingInterface2PF T; + typedef MovingInterfaceBase::IMovingInterface TBase; + string name = string("MovingInterface2PF").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler, + number fluidDensity1, number fluidDensity2)>("domain disc, global handler") + .add_method("init", &T::init) + .add_method("get_integral", &T::get_integral) + .add_method("adjust_for_error", &T::adjust_for_error) + .add_method("initialize_threshold", &T::initialize_threshold) + .add_method("set_threshold", &T::set_threshold, "", "Set Threshold") + .add_method("set_analytic_solution", &T::set_analytic_solution, "", "Set Threshold") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingInterface2PF", tag); + } + + // MovingInterfaceDiffusionFE + { + typedef MovingInterfaceDiffusionFE::MovingInterfaceDiffusionFE T; + typedef MovingInterfaceBase::IMovingInterface TBase; + string name = string("MovingInterfaceDiffusionFE").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, + SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler)>("domain disc, global handler") + .add_method("init", &T::init) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingInterfaceDiffusionFE", tag); + } + */ + // MovingInterfaceDiffusion + { + + typedef MovingInterfaceDiffusion::MovingInterfaceDiffusion T; + typedef MovingInterfaceBase::IMovingInterface TBase; + string name = string("MovingInterfaceDiffusion").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, + SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler)>("domain disc, global handler") + .add_method("init", &T::init) + .add_method("get_integral", &T::get_integral) + .add_method("get_numDoFs", &T::get_numDoFs) + .add_method("set_Nitsche", &T::set_Nitsche) + .add_method("adjust_for_error", &T::adjust_for_error) + .add_method("initialize_threshold", &T::initialize_threshold) + .add_method("set_threshold", &T::set_threshold, "", "Set Threshold") + .add_method("set_analytic_solution", &T::set_analytic_solution, "", "Set Threshold") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingInterfaceDiffusion", tag); + } + +// MovingParticle + { + typedef MovingParticle::MovingParticle T; + typedef MovingInterfaceBase::IMovingInterface TBase; + string name = string("MovingParticle").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, + SmartPtr > cutElementHandler, + number fluidDensity, number fluidKinVisc)>("domain disc, global handler") + .add_method("init", &T::init) + // .add_method("compute_functional_combined", &T::compute_functional_combined) + .add_method("compute_functional", &T::compute_functional) + .add_method("compute_functional_all", &T::compute_functional_all) + .add_method("gradient_descent", &T::gradient_descent) + .add_method("project_directions", &T::project_directions) + .add_method("rescale_directions", &T::rescale_directions) + .add_method("print_velocity", &T::print_velocity) + // .add_method("print_velocity_many_particles", &T::print_velocity_many_particles) + .add_method("print_pressure", &T::print_pressure) + .add_method("print_deltaP", &T::print_deltaP) + .add_method("print_pressure_nodal", &T::print_pressure_nodal) + // .add_method("compute_error_on_circle", &T::compute_error_on_circle) + .add_method("update", &T::update) + .add_method("get_velocity", &T::get_velocity) + .add_method("adjust_global_solution", &T::adjust_global_solution) + .add_method("compute_gradient_local_max", &T::compute_gradient_local_max) + .add_method("set_gravity", &T::set_gravity) + .add_method("set_time_step", &T::set_time_step) + .add_method("set_volume_comp_mode", &T::set_volume_comp_mode) + .add_method("set_StdFV_assembling", &T::set_StdFV_assembling) + .add_method("initialize_threshold", &T::initialize_threshold) + .add_method("get_BndCond", &T::get_BndCond) +// .add_method("get_particles", &T::get_particles) + // methods for parallel many-particle simulations: +#ifdef UG_PARALLEL + .add_method("pre_balancing_update", &T::pre_balancing_update) + .add_method("post_balancing_update", &T::post_balancing_update) +#endif + .add_method("set_repulsive_force", &T::set_repulsive_force) + .add_method("set_glowinski_repulsive_force", &T::set_glowinski_repulsive_force) + .add_method("set_minimum_correction_force", &T::set_minimum_correction_force) + .add_method("set_element_diameter", &T::set_element_diameter) + .add_method("MeanElementDiameter", &T::MeanElementDiameter) + .add_method("set_forceLog", &T::set_forceLog) + .add_method("set_mpi_routine", &T::set_mpi_routine) + .add_method("estimate_repulsive_force_parameters", &T::estimate_repulsive_force_parameters) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingParticle", tag); + } + + // ParticleTransfer + { + typedef ParticleTransfer T; + typedef ITransferOperator TBase; + string name = string("ParticleTransfer").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > approxSpace, SmartPtr > cutElementHandler)>("approxSpace, globalHandler") + .add_method("set_debug", &T::set_debug, "", "") + .add_method("set_use_transposed", &T::set_use_transposed, "", "") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleTransfer", tag); + } + +} + +/** + * Function called for the registration of Algebra dependent parts. + * All Functions and Classes depending on Algebra + * are to be placed here when registering. The method is called for all + * available Algebra types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void Algebra(Registry& reg, string grp) +{ + string suffix = GetAlgebraSuffix(); + string tag = GetAlgebraTag(); +} + +/** + * Function called for the registration of Domain dependent parts + * of the plugin. All Functions and Classes depending on the Domain + * are to be placed here when registering. The method is called for all + * available Domain types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void Domain(Registry& reg, string grp) +{ + string suffix = GetDomainSuffix(); + string tag = GetDomainTag(); + + // ParticleBndCond + { + typedef MovingParticle::ParticleBndCond T; + typedef IElemDisc TBase; + string name = string("ParticleBndCond").append(suffix); + reg.add_class_(name, grp), + reg.add_class_to_group(name, "ParticleBndCond", tag); + } +#ifdef UG_PARALLEL + // ParticleUnificator + { + typedef MovingParticle::ParticleUnificator T; + typedef typename GeomObjBaseTypeByDim::base_obj_type TBaseElem; + typedef parmetis::IUnificator TBase; + string name = string("ParticleUnificator").append(suffix); + reg.add_class_(name, grp) + .template add_constructor)>("") + .add_method("update_particles", &T::update_particles) + .add_method("rebalance", &T::rebalance) + .set_construct_as_smart_pointer(true); + // .add_method("get_weight", &T::get_weight); + // .add_method("reweight", &T::reweight); + reg.add_class_to_group(name, "ParticleUnificator", tag); + } +#endif + +} + +/** + * Function called for the registration of Dimension dependent parts + * of the plugin. All Functions and Classes depending on the Dimension + * are to be placed here when registering. The method is called for all + * available Dimension types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void Dimension(Registry& reg, string grp) +{ + string suffix = GetDimensionSuffix(); + string tag = GetDimensionTag(); + + // CutElementHandlerFlatTop + { + typedef MovingInterfaceBase::CutElementHandlerFlatTop T; + string name = string("CutElementHandlerFlatTop").append(suffix); + reg.add_class_(name, grp) + .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") + .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") + // .add_method("update_prtCoords", &T::update_prtCoords) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "CutElementHandlerFlatTop", tag); + } + + // CutElementHandlerImmersed + { + typedef MovingInterfaceBase::CutElementHandlerImmersed T; + string name = string("CutElementHandlerImmersed").append(suffix); + reg.add_class_(name, grp) + .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "CutElementHandlerImmersed", tag); + } + + // ParticleProvider + { + typedef MovingParticle::ParticleProvider T; + string name = string("ParticleProvider").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleProvider", tag); + } + + + // ParticleProviderSphere + { + typedef MovingParticle::ParticleProviderSphere T; + string name = string("ParticleProviderSphere").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .add_method("add", &T::add) + .add_method("add_moving", &T::add_moving) +// .add_method("get_collision_time", &T::get_collision_time) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleProviderSphere", tag); + } + + // ParticleProviderEllipse + { + typedef MovingParticle::ParticleProviderEllipse T; + string name = string("ParticleProviderEllipse").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .add_method("add", &T::add) + .add_method("add_moving", &T::add_moving) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleProviderEllipse", tag); + } + + // DiffusionInterfaceProvider + { + typedef MovingInterfaceBase::DiffusionInterfaceProvider T; + string name = string("DiffusionInterfaceProvider").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .add_method("add", &T::add) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "DiffusionInterfaceProvider", tag); + } + + +} + + +static void Common(Registry& reg, string grp) +{ + // write numbers into file + /* TODO: obsolete / replace by lua code */ + { + //reg.add_function("writeNumbers", static_cast(&writeNumbers), grp); + } + // write numbers into file + /* TODO: obsolete / replace by lua code */ + { + //reg.add_function("clearFile", static_cast(&clearFile), grp); + } +} + +}; // end Functionality +} // end namespace ParticleLadenFlow + + +/** + * This function is called when the plugin is loaded. + */ +void Init___ParticleLadenFlow(Registry* reg, string grp) +{ + grp.append("SpatialDisc/NavierStokes/"); + typedef ParticleLadenFlow::FunctionalityIncomp Functionality; + + try{ + RegisterDimension2d3dDependent(*reg,grp); + RegisterDomain2d3dDependent(*reg,grp); + RegisterDomain2d3dAlgebraDependent(*reg,grp); + +// RegisterAlgebraDependent(*reg,grp); + + } + UG_REGISTRY_CATCH_THROW(grp); +} + + + +}// namespace ug + + diff --git a/incompressible/particle_laden_flow_plugin.cpp b/incompressible/particle_laden_flow_plugin.cpp new file mode 100644 index 0000000..19b3972 --- /dev/null +++ b/incompressible/particle_laden_flow_plugin.cpp @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt + * Author: Sebastian Reiter + * + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#ifdef UG_PARALLEL + #include "../../Parmetis/src/unificator_interface.h" +#endif + +#include "bridge/util.h" +#include "bridge/util_domain_algebra_dependent.h" + +#include "common/log.h" +#include "lib_disc/function_spaces/grid_function.h" +#include "lib_disc/dof_manager/dof_distribution.h" +#include "fv1/navier_stokes_fv1.h" +#include "incompressible_navier_stokes_base.h" +#include "fv1/bnd/inflow_fv1.h" +#include "bnd/inflow_base.h" + + +#include "lib_disc/spatial_disc/local_to_global/local_to_global_mapper.h" +#include "lib_disc/spatial_disc/immersed_util/gmg_transfer/particle_transfer.h" +#include "fv1/moving_particle/moving_particle.h" +//#include "fv1/two_phase_flow/two_phase_flow.h" + + +using namespace std; +using namespace ug::bridge; + +namespace ug{ +namespace NavierStokes{ + +/** + * Class exporting the functionality of the plugin. All functionality that is to + * be used in scripts or visualization must be registered here. + */ +struct FunctionalityIncompMoving +{ + +/** + * Function called for the registration of Domain and Algebra dependent parts + * of the plugin. All Functions and Classes depending on both Domain and Algebra + * are to be placed here when registering. The method is called for all + * available Domain and Algebra types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void DomainAlgebra(Registry& reg, string grp) +{ + string suffix = GetDomainAlgebraSuffix(); + string tag = GetDomainAlgebraTag(); + + typedef ApproximationSpace approximation_space_type; + typedef GridFunction function_type; + +// IMovingInterfaceBase + { + typedef IMovingInterface T; + string name = string("IMovingInterfaceBase").append(suffix); + reg.add_class_(name, grp); + reg.add_class_to_group(name, "IMovingInterfaceBase", tag); + + } +/* + // MovingInterface2PF + { + typedef MovingInterface2PF::MovingInterface2PF T; + typedef IMovingInterface TBase; + string name = string("MovingInterface2PF").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler, + number fluidDensity1, number fluidDensity2)>("domain disc, global handler") + .add_method("init", &T::init) + .add_method("get_integral", &T::get_integral) + .add_method("adjust_for_error", &T::adjust_for_error) + .add_method("initialize_threshold", &T::initialize_threshold) + .add_method("set_threshold", &T::set_threshold, "", "Set Threshold") + .add_method("set_analytic_solution", &T::set_analytic_solution, "", "Set Threshold") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingInterface2PF", tag); + } + + // MovingInterfaceDiffusionFE + { + typedef MovingInterfaceDiffusionFE::MovingInterfaceDiffusionFE T; + typedef IMovingInterface TBase; + string name = string("MovingInterfaceDiffusionFE").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, + SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler)>("domain disc, global handler") + .add_method("init", &T::init) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingInterfaceDiffusionFE", tag); + } + */ + + +// MovingParticle + { + typedef MovingParticle T; + typedef IMovingInterface TBase; + string name = string("MovingParticle").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, + SmartPtr > cutElementHandler, + number fluidDensity, number fluidKinVisc)>("domain disc, global handler") + .add_method("init", &T::init) + // .add_method("compute_functional_combined", &T::compute_functional_combined) + .add_method("compute_functional", &T::compute_functional) + .add_method("compute_functional_all", &T::compute_functional_all) + .add_method("gradient_descent", &T::gradient_descent) + .add_method("project_directions", &T::project_directions) + .add_method("rescale_directions", &T::rescale_directions) + .add_method("print_velocity", &T::print_velocity) + // .add_method("print_velocity_many_particles", &T::print_velocity_many_particles) + .add_method("print_pressure", &T::print_pressure) + .add_method("print_deltaP", &T::print_deltaP) + .add_method("print_pressure_nodal", &T::print_pressure_nodal) + // .add_method("compute_error_on_circle", &T::compute_error_on_circle) + .add_method("update", &T::update) + .add_method("get_velocity", &T::get_velocity) + .add_method("adjust_global_solution", &T::adjust_global_solution) + .add_method("compute_gradient_local_max", &T::compute_gradient_local_max) + .add_method("set_gravity", &T::set_gravity) + .add_method("set_time_step", &T::set_time_step) + .add_method("set_volume_comp_mode", &T::set_volume_comp_mode) + .add_method("set_StdFV_assembling", &T::set_StdFV_assembling) + .add_method("initialize_threshold", &T::initialize_threshold) + .add_method("get_BndCond", &T::get_BndCond) +// .add_method("get_particles", &T::get_particles) + // methods for parallel many-particle simulations: +#ifdef UG_PARALLEL + .add_method("pre_balancing_update", &T::pre_balancing_update) + .add_method("post_balancing_update", &T::post_balancing_update) +#endif + .add_method("set_repulsive_force", &T::set_repulsive_force) + .add_method("set_glowinski_repulsive_force", &T::set_glowinski_repulsive_force) + .add_method("set_minimum_correction_force", &T::set_minimum_correction_force) + .add_method("set_element_diameter", &T::set_element_diameter) + .add_method("MeanElementDiameter", &T::MeanElementDiameter) + .add_method("set_forceLog", &T::set_forceLog) + .add_method("set_mpi_routine", &T::set_mpi_routine) + .add_method("estimate_repulsive_force_parameters", &T::estimate_repulsive_force_parameters) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingParticle", tag); + } + + // ParticleTransfer + { + typedef ParticleTransfer T; + typedef ITransferOperator TBase; + string name = string("ParticleTransfer").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > approxSpace, SmartPtr > cutElementHandler)>("approxSpace, globalHandler") + .add_method("set_debug", &T::set_debug, "", "") + .add_method("set_use_transposed", &T::set_use_transposed, "", "") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleTransfer", tag); + } + +} + +/** + * Function called for the registration of Algebra dependent parts. + * All Functions and Classes depending on Algebra + * are to be placed here when registering. The method is called for all + * available Algebra types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void Algebra(Registry& reg, string grp) +{ + string suffix = GetAlgebraSuffix(); + string tag = GetAlgebraTag(); +} + +/** + * Function called for the registration of Domain dependent parts + * of the plugin. All Functions and Classes depending on the Domain + * are to be placed here when registering. The method is called for all + * available Domain types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void Domain(Registry& reg, string grp) +{ + string suffix = GetDomainSuffix(); + string tag = GetDomainTag(); + + // ParticleBndCond + { + typedef ParticleBndCond T; + typedef IElemDisc TBase; + string name = string("ParticleBndCond").append(suffix); + reg.add_class_(name, grp), + reg.add_class_to_group(name, "ParticleBndCond", tag); + } +#ifdef UG_PARALLEL + // ParticleUnificator + { + typedef ParticleUnificator T; + typedef typename GeomObjBaseTypeByDim::base_obj_type TBaseElem; + typedef parmetis::IUnificator TBase; + string name = string("ParticleUnificator").append(suffix); + reg.add_class_(name, grp) + .template add_constructor)>("") + .add_method("update_particles", &T::update_particles) + .add_method("rebalance", &T::rebalance) + .set_construct_as_smart_pointer(true); + // .add_method("get_weight", &T::get_weight); + // .add_method("reweight", &T::reweight); + reg.add_class_to_group(name, "ParticleUnificator", tag); + } +#endif + +} + +/** + * Function called for the registration of Dimension dependent parts + * of the plugin. All Functions and Classes depending on the Dimension + * are to be placed here when registering. The method is called for all + * available Dimension types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void Dimension(Registry& reg, string grp) +{ + string suffix = GetDimensionSuffix(); + string tag = GetDimensionTag(); + + // CutElementHandlerFlatTop + { + typedef CutElementHandlerFlatTop T; + string name = string("CutElementHandlerFlatTop").append(suffix); + reg.add_class_(name, grp) + .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") + .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") + // .add_method("update_prtCoords", &T::update_prtCoords) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "CutElementHandlerFlatTop", tag); + } + + + // ParticleProvider + { + typedef ParticleProvider T; + string name = string("ParticleProvider").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleProvider", tag); + } + + + // ParticleProviderSphere + { + typedef ParticleProviderSphere T; + string name = string("ParticleProviderSphere").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .add_method("add", &T::add) + .add_method("add_moving", &T::add_moving) +// .add_method("get_collision_time", &T::get_collision_time) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleProviderSphere", tag); + } + + // ParticleProviderEllipse + { + typedef ParticleProviderEllipse T; + string name = string("ParticleProviderEllipse").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .add_method("add", &T::add) + .add_method("add_moving", &T::add_moving) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleProviderEllipse", tag); + } + + +} + + +static void Common(Registry& reg, string grp) +{ + // write numbers into file + /* TODO: obsolete / replace by lua code */ + { + //reg.add_function("writeNumbers", static_cast(&writeNumbers), grp); + } + // write numbers into file + /* TODO: obsolete / replace by lua code */ + { + //reg.add_function("clearFile", static_cast(&clearFile), grp); + } +} + +}; // end Functionality +} // end namespace NavierStokes + + +/** + * This function is called when the plugin is loaded. + */ +void Init___ParticleLadenFlow(Registry* reg, string grp) +{ + grp.append("SpatialDisc/NavierStokes/"); + typedef NavierStokes::FunctionalityIncompMoving Functionality; + + try{ + RegisterDimension2d3dDependent(*reg,grp); + RegisterDomain2d3dDependent(*reg,grp); + RegisterDomain2d3dAlgebraDependent(*reg,grp); + } + UG_REGISTRY_CATCH_THROW(grp); +} + + + +}// namespace ug + + diff --git a/incompressible/particle_laden_flow_plugin.h b/incompressible/particle_laden_flow_plugin.h new file mode 100644 index 0000000..5e909db --- /dev/null +++ b/incompressible/particle_laden_flow_plugin.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015: G-CSC, Goethe University Frankfurt + * Author: Andreas Vogel + * + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#ifndef MOVING_PARTICLE_PLUGIN_H_ +#define MOVING_PARTICLE_PLUGIN_H_ + + +namespace ug{ + +#include "bridge/util.h" +#include + + void + Init___ParticleLadenFlow(ug::bridge::Registry* reg, std::string grp); + + +} // end namespace ug + +#endif /* MOVING_PARTICLE_PLUGIN_H_ */ diff --git a/incompressible/particle_laden_flow_plugin_origJonas.cpp b/incompressible/particle_laden_flow_plugin_origJonas.cpp new file mode 100644 index 0000000..8c6feca --- /dev/null +++ b/incompressible/particle_laden_flow_plugin_origJonas.cpp @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt + * Author: Sebastian Reiter + * + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#ifdef UG_PARALLEL + #include "../../Parmetis/src/unificator_interface.h" +#endif + +#include "bridge/util.h" +#include "bridge/util_domain_algebra_dependent.h" + +#include "common/log.h" +#include "lib_disc/function_spaces/grid_function.h" +#include "lib_disc/dof_manager/dof_distribution.h" +#include "fv1/navier_stokes_fv1.h" +#include "incompressible_navier_stokes_base.h" +#include "fv1/bnd/inflow_fv1.h" +#include "bnd/inflow_base.h" + + +#include "lib_disc/spatial_disc/local_to_global/local_to_global_mapper.h" +#include "fv1/immersed_interface_base/gmg_transfer/particle_transfer.h" +#include "fv1/moving_particle/interface_handler_particle.h" +#include "fv1/moving_particle/moving_particle.h" +//#include "fv1/diffusion_interface/interface_handler_diffusion.h" +//#include "fv1/diffusion_interface/diffusion_interface.h" +//#include "fv1/two_phase_flow/two_phase_flow.h" + + +using namespace std; +using namespace ug::bridge; + +namespace ug{ +namespace ParticleLadenFlow{ + +/** + * Class exporting the functionality of the plugin. All functionality that is to + * be used in scripts or visualization must be registered here. + */ +struct FunctionalityIncomp +{ + +/** + * Function called for the registration of Domain and Algebra dependent parts + * of the plugin. All Functions and Classes depending on both Domain and Algebra + * are to be placed here when registering. The method is called for all + * available Domain and Algebra types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void DomainAlgebra(Registry& reg, string grp) +{ + string suffix = GetDomainAlgebraSuffix(); + string tag = GetDomainAlgebraTag(); + + typedef ApproximationSpace approximation_space_type; + typedef GridFunction function_type; + +// IMovingInterfaceBase + { + typedef MovingInterfaceBase::IMovingInterface T; + string name = string("IMovingInterfaceBase").append(suffix); + reg.add_class_(name, grp); + reg.add_class_to_group(name, "IMovingInterfaceBase", tag); + + } +/* + // MovingInterface2PF + { + typedef MovingInterface2PF::MovingInterface2PF T; + typedef MovingInterfaceBase::IMovingInterface TBase; + string name = string("MovingInterface2PF").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler, + number fluidDensity1, number fluidDensity2)>("domain disc, global handler") + .add_method("init", &T::init) + .add_method("get_integral", &T::get_integral) + .add_method("adjust_for_error", &T::adjust_for_error) + .add_method("initialize_threshold", &T::initialize_threshold) + .add_method("set_threshold", &T::set_threshold, "", "Set Threshold") + .add_method("set_analytic_solution", &T::set_analytic_solution, "", "Set Threshold") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingInterface2PF", tag); + } + + // MovingInterfaceDiffusionFE + { + typedef MovingInterfaceDiffusionFE::MovingInterfaceDiffusionFE T; + typedef MovingInterfaceBase::IMovingInterface TBase; + string name = string("MovingInterfaceDiffusionFE").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, + SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler)>("domain disc, global handler") + .add_method("init", &T::init) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingInterfaceDiffusionFE", tag); + } + + // MovingInterfaceDiffusion + { + + typedef MovingInterfaceDiffusion::MovingInterfaceDiffusion T; + typedef MovingInterfaceBase::IMovingInterface TBase; + string name = string("MovingInterfaceDiffusion").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, + SmartPtr > interfaceProvider, + SmartPtr > cutElementHandler)>("domain disc, global handler") + .add_method("init", &T::init) + .add_method("get_integral", &T::get_integral) + .add_method("set_Nitsche", &T::set_Nitsche) + .add_method("adjust_for_error", &T::adjust_for_error) + .add_method("initialize_threshold", &T::initialize_threshold) + .add_method("set_threshold", &T::set_threshold, "", "Set Threshold") + .add_method("set_analytic_solution", &T::set_analytic_solution, "", "Set Threshold") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingInterfaceDiffusion", tag); + } + */ +// MovingParticle + { + typedef MovingParticle::MovingParticle T; + typedef MovingInterfaceBase::IMovingInterface TBase; + string name = string("MovingParticle").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > ass, + SmartPtr > spMaster, + SmartPtr > cutElementHandler, + number fluidDensity, number fluidKinVisc)>("domain disc, global handler") + .add_method("init", &T::init) +// .add_method("compute_functional_combined", &T::compute_functional_combined) + .add_method("compute_functional", &T::compute_functional) + .add_method("compute_functional_all", &T::compute_functional_all) + .add_method("gradient_descent", &T::gradient_descent) + .add_method("project_directions", &T::project_directions) + .add_method("rescale_directions", &T::rescale_directions) + .add_method("print_velocity", &T::print_velocity) +// .add_method("print_velocity_many_particles", &T::print_velocity_many_particles) + .add_method("print_pressure", &T::print_pressure) + .add_method("print_deltaP", &T::print_deltaP) + .add_method("print_pressure_nodal", &T::print_pressure_nodal) +// .add_method("compute_error_on_circle", &T::compute_error_on_circle) + .add_method("update", &T::update) + .add_method("get_velocity", &T::get_velocity) + .add_method("adjust_global_solution", &T::adjust_global_solution) + .add_method("compute_gradient_local_max", &T::compute_gradient_local_max) + .add_method("set_gravity", &T::set_gravity) + .add_method("set_time_step", &T::set_time_step) + .add_method("set_volume_comp_mode", &T::set_volume_comp_mode) + .add_method("set_StdFV_assembling", &T::set_StdFV_assembling) + .add_method("initialize_threshold", &T::initialize_threshold) + .add_method("get_BndCond", &T::get_BndCond) +// .add_method("get_particles", &T::get_particles) + // methods for parallel many-particle simulations: +#ifdef UG_PARALLEL + .add_method("pre_balancing_update", &T::pre_balancing_update) + .add_method("post_balancing_update", &T::post_balancing_update) +#endif + .add_method("set_repulsive_force", &T::set_repulsive_force) + .add_method("set_glowinski_repulsive_force", &T::set_glowinski_repulsive_force) + .add_method("set_minimum_correction_force", &T::set_minimum_correction_force) + .add_method("set_element_diameter", &T::set_element_diameter) + .add_method("MeanElementDiameter", &T::MeanElementDiameter) + .add_method("set_forceLog", &T::set_forceLog) + .add_method("set_mpi_routine", &T::set_mpi_routine) + .add_method("estimate_repulsive_force_parameters", &T::estimate_repulsive_force_parameters) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "MovingParticle", tag); + } + + // ParticleTransfer + { + typedef ParticleTransfer T; + typedef ITransferOperator TBase; + string name = string("ParticleTransfer").append(suffix); + reg.add_class_(name, grp) + .template add_constructor > approxSpace, SmartPtr > cutElementHandler)>("approxSpace, globalHandler") + .add_method("set_debug", &T::set_debug, "", "") + .add_method("set_use_transposed", &T::set_use_transposed, "", "") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleTransfer", tag); + } + +} + +/** + * Function called for the registration of Algebra dependent parts. + * All Functions and Classes depending on Algebra + * are to be placed here when registering. The method is called for all + * available Algebra types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void Algebra(Registry& reg, string grp) +{ + string suffix = GetAlgebraSuffix(); + string tag = GetAlgebraTag(); +} + +/** + * Function called for the registration of Domain dependent parts + * of the plugin. All Functions and Classes depending on the Domain + * are to be placed here when registering. The method is called for all + * available Domain types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void Domain(Registry& reg, string grp) +{ + string suffix = GetDomainSuffix(); + string tag = GetDomainTag(); + + // ParticleBndCond + { + typedef MovingParticle::ParticleBndCond T; + typedef IElemDisc TBase; + string name = string("ParticleBndCond").append(suffix); + reg.add_class_(name, grp), + reg.add_class_to_group(name, "ParticleBndCond", tag); + } + +#ifdef UG_PARALLEL + // ParticleUnificator + { + typedef MovingParticle::ParticleUnificator T; + typedef typename GeomObjBaseTypeByDim::base_obj_type TBaseElem; + typedef parmetis::IUnificator TBase; + string name = string("ParticleUnificator").append(suffix); + reg.add_class_(name, grp) + .template add_constructor)>("") + .add_method("update_particles", &T::update_particles) + .add_method("rebalance", &T::rebalance) + .set_construct_as_smart_pointer(true); + // .add_method("get_weight", &T::get_weight); + // .add_method("reweight", &T::reweight); + reg.add_class_to_group(name, "ParticleUnificator", tag); + } +#endif + +} + +/** + * Function called for the registration of Dimension dependent parts + * of the plugin. All Functions and Classes depending on the Dimension + * are to be placed here when registering. The method is called for all + * available Dimension types, based on the current build options. + * + * @param reg registry + * @param parentGroup group for sorting of functionality + */ +template +static void Dimension(Registry& reg, string grp) +{ + string suffix = GetDimensionSuffix(); + string tag = GetDimensionTag(); + + // CutElementHandlerFlatTop + { + typedef MovingInterfaceBase::CutElementHandlerFlatTop T; + string name = string("CutElementHandlerFlatTop").append(suffix); + reg.add_class_(name, grp) + .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") + .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") + // .add_method("update_prtCoords", &T::update_prtCoords) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "CutElementHandlerFlatTop", tag); + } + /* + // CutElementHandlerImmersed + { + typedef MovingInterfaceBase::CutElementHandlerImmersed T; + string name = string("CutElementHandlerImmersed").append(suffix); + reg.add_class_(name, grp) + .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "CutElementHandlerImmersed", tag); + } + */ + // ParticleProvider + { + typedef MovingParticle::ParticleProvider T; + string name = string("ParticleProvider").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleProvider", tag); + } + + + // ParticleProviderSphere + { + typedef MovingParticle::ParticleProviderSphere T; + string name = string("ParticleProviderSphere").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .add_method("add", &T::add) + .add_method("add_moving", &T::add_moving) +// .add_method("get_collision_time", &T::get_collision_time) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleProviderSphere", tag); + } + + // ParticleProviderEllipse + { + typedef MovingParticle::ParticleProviderEllipse T; + string name = string("ParticleProviderEllipse").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .add_method("add", &T::add) + .add_method("add_moving", &T::add_moving) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "ParticleProviderEllipse", tag); + } +/* + // DiffusionInterfaceProvider + { + typedef MovingInterfaceBase::DiffusionInterfaceProvider T; + string name = string("DiffusionInterfaceProvider").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("") + .add_method("print", &T::print) + .add_method("add", &T::add) + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "DiffusionInterfaceProvider", tag); + } + */ + +} + + +static void Common(Registry& reg, string grp) +{ + // write numbers into file + /* TODO: obsolete / replace by lua code */ + { + //reg.add_function("writeNumbers", static_cast(&writeNumbers), grp); + } + // write numbers into file + /* TODO: obsolete / replace by lua code */ + { + //reg.add_function("clearFile", static_cast(&clearFile), grp); + } +} + +}; // end Functionality +} // end namespace ParticleLadenFlow + + +/** + * This function is called when the plugin is loaded. + */ +void Init___ParticleLadenFlow(Registry* reg, string grp) +{ + grp.append("SpatialDisc/NavierStokes/"); + typedef ParticleLadenFlow::FunctionalityIncomp Functionality; + + try{ + RegisterDimension2d3dDependent(*reg,grp); + RegisterDomain2d3dDependent(*reg,grp); + RegisterDomain2d3dAlgebraDependent(*reg,grp); + +// RegisterAlgebraDependent(*reg,grp); + + } + UG_REGISTRY_CATCH_THROW(grp); +} + + + +}// namespace ug + + diff --git a/register_navier_stokes.h b/register_navier_stokes.h index fd4969e..8d16618 100644 --- a/register_navier_stokes.h +++ b/register_navier_stokes.h @@ -40,6 +40,7 @@ namespace ug{ void Init___CompressibleNavierStokes(bridge::Registry* reg, std::string grp); void Init___IncompressibleNavierStokes(bridge::Registry* reg, std::string grp); +void Init___ParticleLadenFlow(bridge::Registry* reg, std::string grp); }// namespace ug diff --git a/upwind.cpp b/upwind.cpp index 708b14a..3b9d050 100644 --- a/upwind.cpp +++ b/upwind.cpp @@ -130,6 +130,48 @@ compute(const HCRFVGeometry* geo, // Full Upwind ///////////////////////////////////////////////////////////////////////////// + +template +template +void +NavierStokesFullUpwind:: +compute(const DimFV1FTGeometry >* geo, + const MathVector vIPVel[maxNumSCVF], + number vUpShapeSh[maxNumSCVF][maxNumSH], + number vUpShapeIp[maxNumSCVF][maxNumSCVF], + number vConvLength[maxNumSCVF]) +{ + // two help vectors + MathVector dist; + + // get corners of elem + const MathVector* corners = geo->corners(); + + // set shapes + for(size_t ip = 0; ip < geo->num_scvf(); ++ip) + { + // get SubControlVolumeFace + const typename DimFV1FTGeometry >::SCVF& scvf = geo->scvf(ip); + + // reset shapes to zero for all IPs + for (size_t sh = 0; sh < scvf.num_sh(); ++sh) + vUpShapeSh[ip][sh]=0.0; + + // switch upwind + const number flux = VecDot(scvf.normal(), vIPVel[ip]); + if(flux > 0.0) + { + vUpShapeSh[ip][scvf.from()] = 1.0; + vConvLength[ip] = VecDistance(scvf.global_ip(), corners[scvf.from()]); + } + else + { + vUpShapeSh[ip][scvf.to()] = 1.0; + vConvLength[ip] = VecDistance(scvf.global_ip(), corners[scvf.to()]); + } + } +} + template template void @@ -378,6 +420,7 @@ void GetNodeNextToCut(size_t& coOut, } } + template template void @@ -388,47 +431,47 @@ compute(const FV1Geometry* geo, number vUpShapeIp[maxNumSCVF][maxNumSCVF], number vConvLength[maxNumSCVF]) { -// corners of geometry - const MathVector* vCornerCoords = geo->corners(); - -// loop all scvf - for(size_t ip = 0; ip < geo->num_scvf(); ++ip) - { - // get SubControlVolumeFace - const typename FV1Geometry::SCVF& scvf = geo->scvf(ip); - - // reset shapes to zero - for(size_t sh = 0; sh < scvf.num_sh(); ++sh) - vUpShapeSh[ip][sh] = 0.0; - - // if the velocity is zero, there will be no possibility to find the - // cutted side. In this case we have no velocity and therefore there is - // no convection. We set all upwind shapes to zero. - if(VecTwoNorm(vIPVel[ip]) < 1e-14) { - // \todo: (optional) A convection length is not really defined. - // but in the computation of a stabilization the term cancels, so - // we only have to ensure that the conv_lengh is non-zero - vConvLength[ip] = 1.0; - continue; - } - - // upwind corner - size_t sh = 0; - - // find upwind node - try{ - GetNodeNextToCut::ref_elem_type, dim> - (sh, scvf.global_ip(), vIPVel[ip], vCornerCoords); - }UG_CATCH_THROW("GetSkewedUpwindShapes: Cannot find upwind node."); - - // set upwind corner - vUpShapeSh[ip][sh] = 1.0; - - // compute convection length - vConvLength[ip] = VecDistance(scvf.global_ip(), vCornerCoords[sh]); - } + // corners of geometry + const MathVector* vCornerCoords = geo->corners(); + + // loop all scvf + for(size_t ip = 0; ip < geo->num_scvf(); ++ip) + { + // get SubControlVolumeFace + const typename FV1Geometry::SCVF& scvf = geo->scvf(ip); + + // reset shapes to zero + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + vUpShapeSh[ip][sh] = 0.0; + + // if the velocity is zero, there will be no possibility to find the + // cutted side. In this case we have no velocity and therefore there is + // no convection. We set all upwind shapes to zero. + if(VecTwoNorm(vIPVel[ip]) < 1e-14) { + // \todo: (optional) A convection length is not really defined. + // but in the computation of a stabilization the term cancels, so + // we only have to ensure that the conv_lengh is non-zero + vConvLength[ip] = 1.0; + continue; + } + + // upwind corner + size_t sh = 0; + + // find upwind node + try{ + GetNodeNextToCut::ref_elem_type, dim> + (sh, scvf.global_ip(), vIPVel[ip], vCornerCoords); + }UG_CATCH_THROW("GetSkewedUpwindShapes: Cannot find upwind node."); + + // set upwind corner + vUpShapeSh[ip][sh] = 1.0; + + // compute convection length + vConvLength[ip] = VecDistance(scvf.global_ip(), vCornerCoords[sh]); + } } - + template template void @@ -501,7 +544,6 @@ compute(const CRFVGeometry* geo, ///////////////////////////////////////////////////////////////////////////// // Linear Profile Skewed Upwind ///////////////////////////////////////////////////////////////////////////// - template template void @@ -511,6 +553,177 @@ compute(const FV1Geometry* geo, number vUpShapeSh[maxNumSCVF][maxNumSH], number vUpShapeIp[maxNumSCVF][maxNumSCVF], number vConvLength[maxNumSCVF]) +{ + // corners of geometry + const MathVector* vCornerCoords = geo->corners(); + + // loop all scvf + for(size_t ip = 0; ip < geo->num_scvf(); ++ip) + { + // get SubControlVolumeFace + const typename FV1Geometry::SCVF& scvf = geo->scvf(ip); + + // reset shapes to zero + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + vUpShapeSh[ip][sh] = 0.0; + + // if the velocity is zero, there will be no possibility to find the + // cutted side. In this case we have no velocity and therefore there is + // no convection. We set all upwind shapes to zero. + if(VecTwoNorm(vIPVel[ip]) < 1e-14) { + // \todo: (optional) A convection length is not really defined. + // but in the computation of a stabilization the term cancels, so + // we only have to ensure that the conv_lengh is non-zero + vConvLength[ip] = 1.0; + continue; + } + + // side and intersection vectors + static const int refDim = FV1Geometry::dim; + size_t side = 0; + MathVector globalIntersection; + MathVector localIntersection; + + // find local intersection and side + try{ + ElementSideRayIntersection::ref_elem_type, dim> + ( side, globalIntersection, localIntersection, + scvf.global_ip(), vIPVel[ip], false /* search upwind */, vCornerCoords); + }UG_CATCH_THROW("GetLinearProfileSkewedUpwindShapes: Cannot find cut side."); + + // get linear trial space + static const ReferenceObjectID roid = reference_element_traits::reference_element_type::REFERENCE_OBJECT_ID; + const LocalShapeFunctionSet& TrialSpace = + LocalFiniteElementProvider::get(roid, LFEID(LFEID::LAGRANGE, dim, 1)); + + // get Reference Element + typedef typename FV1Geometry::ref_elem_type ref_elem_type; + static const ref_elem_type& rRefElem + = Provider::get(); + + // loop corners of side + for(size_t j = 0; j < rRefElem.num(dim-1, side, 0); ++j) + { + // get corner + const size_t co = rRefElem.id(dim-1, side, 0, j); + + // evaluate trial space + vUpShapeSh[ip][co] = TrialSpace.shape(co, localIntersection); + } + + // compute conv length + vConvLength[ip] = VecDistance(scvf.global_ip(), globalIntersection); + } +} + +////////////////////////////////////////////////////////////////////////////////// +// +// DimWrapper_ElementSideRayIntersection(): +// +// Wrapper functions in order to call the method 'ElementSideRayIntersection' +// for different dimensions and reference element types. +// For the 'DimFV1FTGeometry' the reference element type can change, therefore +// a different call of the method 'ElementSideRayIntersection' is necessary +// for call within 'NavierStokesLinearProfileSkewedUpwind()' +// +////////////////////////////////////////////////////////////////////////////////// + + +template +inline void DimWrapper_ElementSideRayIntersection(const ReferenceObjectID roid, size_t& sideOut, + MathVector& GlobalIntersectionPointOut, + MathVector& LocalIntersectionPoint, + const MathVector& From, const MathVector& Direction, + bool bPositiv, const MathVector* vCornerCoords); + +template <> +inline void DimWrapper_ElementSideRayIntersection<1>(const ReferenceObjectID roid, size_t& sideOut, + MathVector<1>& GlobalIntersectionPointOut, + MathVector<1>& LocalIntersectionPoint, + const MathVector<1>& From, const MathVector<1>& Direction, + bool bPositiv, const MathVector<1>* vCornerCoords) +{ + UG_THROW("in DimWrapper_ElementSideRayIntersection<1>: not implemented for 1d!\n") +} + +template <> +inline void DimWrapper_ElementSideRayIntersection<2>(const ReferenceObjectID roid, size_t& sideOut, + MathVector<2>& GlobalIntersectionPointOut, + MathVector<2>& LocalIntersectionPoint, + const MathVector<2>& From, const MathVector<2>& Direction, + bool bPositiv, const MathVector<2>* vCornerCoords) +{ + switch(roid) + { + case ROID_TRIANGLE: try{ + ElementSideRayIntersectionWrapper::reference_element_type, 2, 2>:: + apply(sideOut, GlobalIntersectionPointOut, LocalIntersectionPoint, From, Direction, + bPositiv, vCornerCoords); + }UG_CATCH_THROW("DimWrapper_ElementSideRayIntersection<2>: Cannot find cut side."); + break; + case ROID_QUADRILATERAL: try{ + ElementSideRayIntersectionWrapper::reference_element_type, 2, 2>:: + apply(sideOut, GlobalIntersectionPointOut, LocalIntersectionPoint, From, Direction, + bPositiv, vCornerCoords); + }UG_CATCH_THROW("DimWrapper_ElementSideRayIntersection<2>: Cannot find cut side."); + break; + default: UG_THROW("Reference Element type for roid "< +inline void DimWrapper_ElementSideRayIntersection<3>(const ReferenceObjectID roid, size_t& sideOut, + MathVector<3>& GlobalIntersectionPointOut, + MathVector<3>& LocalIntersectionPoint, + const MathVector<3>& From, const MathVector<3>& Direction, + bool bPositiv, const MathVector<3>* vCornerCoords) +{ + switch(roid) + { + case ROID_TETRAHEDRON: try{ + ElementSideRayIntersectionWrapper::reference_element_type, 3, 3>:: + apply(sideOut, GlobalIntersectionPointOut, LocalIntersectionPoint, From, Direction, + bPositiv, vCornerCoords); + }UG_CATCH_THROW("DimWrapper_ElementSideRayIntersection<3> - ROID_TETRAHEDRON: Cannot find cut side."); + break; + case ROID_PYRAMID: try{ + ElementSideRayIntersectionWrapper::reference_element_type, 3, 3>:: + apply(sideOut, GlobalIntersectionPointOut, LocalIntersectionPoint, From, Direction, + bPositiv, vCornerCoords); + }UG_CATCH_THROW("DimWrapper_ElementSideRayIntersection<3> - ROID_PYRAMID: Cannot find cut side."); + break; + case ROID_PRISM: try{ + ElementSideRayIntersectionWrapper::reference_element_type, 3, 3>:: + apply(sideOut, GlobalIntersectionPointOut, LocalIntersectionPoint, From, Direction, + bPositiv, vCornerCoords); + }UG_CATCH_THROW("DimWrapper_ElementSideRayIntersection<3> - ROID_PRISM: Cannot find cut side."); + break; + case ROID_HEXAHEDRON: try{ + ElementSideRayIntersectionWrapper::reference_element_type, 3, 3>:: + apply(sideOut, GlobalIntersectionPointOut, LocalIntersectionPoint, From, Direction, + bPositiv, vCornerCoords); + }UG_CATCH_THROW("DimWrapper_ElementSideRayIntersection<3> - ROID_HEXAHEDRON: Cannot find cut side."); + break; + case ROID_OCTAHEDRON: try{ + ElementSideRayIntersectionWrapper::reference_element_type, 3, 3>:: + apply(sideOut, GlobalIntersectionPointOut, LocalIntersectionPoint, From, Direction, + bPositiv, vCornerCoords); + }UG_CATCH_THROW("DimWrapper_ElementSideRayIntersection<3> - ROID_OCTAHEDRON: Cannot find cut side."); + break; + default: UG_THROW("Reference Element type for roid "< +template +void +NavierStokesLinearProfileSkewedUpwind:: +compute(const DimFV1FTGeometry >* geo, + const MathVector vIPVel[maxNumSCVF], + number vUpShapeSh[maxNumSCVF][maxNumSH], + number vUpShapeIp[maxNumSCVF][maxNumSCVF], + number vConvLength[maxNumSCVF]) { // corners of geometry const MathVector* vCornerCoords = geo->corners(); @@ -519,8 +732,9 @@ compute(const FV1Geometry* geo, for(size_t ip = 0; ip < geo->num_scvf(); ++ip) { // get SubControlVolumeFace - const typename FV1Geometry::SCVF& scvf = geo->scvf(ip); - + typedef DimFV1FTGeometry > TFVGeom; + const typename TFVGeom::SCVF& scvf = geo->scvf(ip); + // reset shapes to zero for(size_t sh = 0; sh < scvf.num_sh(); ++sh) vUpShapeSh[ip][sh] = 0.0; @@ -537,28 +751,30 @@ compute(const FV1Geometry* geo, } // side and intersection vectors - static const int refDim = FV1Geometry::dim; + static const int refDim = TFVGeom::dim; size_t side = 0; MathVector globalIntersection; - MathVector localIntersection; +// MathVector localIntersection; + MathVector localIntersection; + // get reference object ID + const ReferenceObjectID roid = geo->get_roid(); + // find local intersection and side try{ - ElementSideRayIntersection::ref_elem_type, dim> - ( side, globalIntersection, localIntersection, - scvf.global_ip(), vIPVel[ip], false /* search upwind */, vCornerCoords); - }UG_CATCH_THROW("GetLinearProfileSkewedUpwindShapes: Cannot find cut side."); + DimWrapper_ElementSideRayIntersection + ( roid, side, globalIntersection, localIntersection, + scvf.global_ip(), vIPVel[ip], false , vCornerCoords); + }UG_CATCH_THROW("GetLinearProfileSkewedUpwindShapes: Cannot find cut side."); // get linear trial space - static const ReferenceObjectID roid = reference_element_traits::reference_element_type::REFERENCE_OBJECT_ID; - const LocalShapeFunctionSet& TrialSpace = + const LocalShapeFunctionSet& TrialSpace = LocalFiniteElementProvider::get(roid, LFEID(LFEID::LAGRANGE, dim, 1)); // get Reference Element - typedef typename FV1Geometry::ref_elem_type ref_elem_type; - static const ref_elem_type& rRefElem - = Provider::get(); + const DimReferenceElement& rRefElem = ReferenceElementProvider::get(roid); + // loop corners of side for(size_t j = 0; j < rRefElem.num(dim-1, side, 0); ++j) { @@ -639,6 +855,154 @@ compute(const CRFVGeometry* geo, ///////////////////////////////////////////////////////////////////////////// // Positive Upwind ///////////////////////////////////////////////////////////////////////////// + +template +template +void +NavierStokesPositiveUpwind:: +compute(const DimFV1FTGeometry >* geo, + const MathVector vIPVel[maxNumSCVF], + number vUpShapeSh[maxNumSCVF][maxNumSH], + number vUpShapeIp[maxNumSCVF][maxNumSCVF], + number vConvLength[maxNumSCVF]) +{ + + // 1. Reset values and compute ip velocities and Compute mass fluxes at ip's + + // vector for flux values + std::vector vMassFlux(geo->num_scvf(), 0.0); + std::vector vHasFlux(geo->num_scvf(), true); + + typedef DimFV1FTGeometry > TFVGeom; + + // loop all scvf + const number eps = std::numeric_limits::epsilon() * 10; + size_t bNumNoFlux = 0; + for(size_t ip = 0; ip < geo->num_scvf(); ++ip) + { + // get SubControlVolumeFace + const typename TFVGeom::SCVF& scvf = geo->scvf(ip); + + // reset shapes w.r.t corner value to zero + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + vUpShapeSh[ip][sh] = 0.0; + + // reset shapes w.r.t. ip value to zero and extract ip vel + for(size_t j = 0; j < geo->num_scvf(); ++j) + vUpShapeIp[ip][j] = 0.0; + + const number normSq = VecTwoNormSq(vIPVel[ip]); + if(fabs(normSq) <= eps) + { + vUpShapeSh[ip][scvf.from()] = 0.5; + vUpShapeSh[ip][scvf.to()] = 0.5; + vHasFlux[ip] = false; + bNumNoFlux++; + continue; + } + + vMassFlux[ip] = VecProd(vIPVel[ip], scvf.normal()); + const number vel = std::sqrt(normSq); + const number len = VecTwoNorm(scvf.normal()); + if(fabs(vMassFlux[ip] / std::sqrt(vel*len)) <= eps) + { + vUpShapeSh[ip][scvf.from()] = 0.5; + vUpShapeSh[ip][scvf.to()] = 0.5; + vHasFlux[ip] = false; + bNumNoFlux++; + continue; + } + } + + + // 2. Handle each SCV separately + if(bNumNoFlux != geo->num_scvf()) + { + for(size_t sh = 0; sh < geo->num_sh(); ++sh) + { + // reset inflow, outflow + number m_in = 0, m_out = 0; + std::vector vSCVIP; + std::vector vFlux; + + // loop subcontrol volume faces + for(size_t ip = 0; ip < geo->num_scvf(); ++ip) + { + // if no flux skip + if(!vHasFlux[ip]) continue; + + // get SubControlVolumeFace + const typename TFVGeom::SCVF& scvf = geo->scvf(ip); + + // if scvf is part of the scv, add fluxes + if(scvf.from() == sh) + { + // normal directed outwards + vSCVIP.push_back(ip); + vFlux.push_back( vMassFlux[ip] ); + m_in += -1.0 * std::min(vMassFlux[ip], 0.0); + m_out += std::max(vMassFlux[ip], 0.0); + } + else if (scvf.to() == sh) + { + // normal directed inwards + vSCVIP.push_back(ip); + vFlux.push_back( -1.0 * vMassFlux[ip] ); + m_in += -1.0 * std::min(-1.0 * vMassFlux[ip], 0.0); + m_out += std::max(-1.0 * vMassFlux[ip], 0.0); + } + } + + // compute F + number F = std::max(m_in, m_out); + + // set shapes + for(size_t i = 0; i < vSCVIP.size(); ++i) + { + if(vFlux[i] > 0) + { + number sum = 0.0; + for(size_t j = 0; j < vSCVIP.size(); ++j) + { + if(vFlux[j] < 0) + { + // set ip shapes + sum += vUpShapeIp[vSCVIP[i]][vSCVIP[j]] = -1.0 * vFlux[j] / F; + } + } + // set nodal shapes + vUpShapeSh[vSCVIP[i]][sh] = 1.0 - sum; + } + } + } + } + + // 3. compute convection length + + // corners of geometry + const MathVector* vCornerCoords = geo->corners(); + + // compute upwind point + MathVector upPos; + for(size_t ip = 0; ip < geo->num_scvf(); ++ip) + { + // get SubControlVolumeFace + const typename TFVGeom::SCVF& scvf = geo->scvf(ip); + + // reset upwind point + VecSet(upPos, 0.0); + + // sum up contributions + for (size_t sh = 0; sh < scvf.num_sh(); ++sh) + VecScaleAppend(upPos, vUpShapeSh[ip][sh], vCornerCoords[sh]); + for (size_t j = 0; j < geo->num_scvf(); ++j) + VecScaleAppend(upPos, vUpShapeIp[ip][j], geo->scvf(j).global_ip()); + + // save convection length + vConvLength[ip] = VecDistance(scvf.global_ip(), upPos); + } +} + template template diff --git a/upwind.h b/upwind.h index 49f43b1..51a501e 100644 --- a/upwind.h +++ b/upwind.h @@ -44,6 +44,7 @@ #include "lib_disc/spatial_disc/disc_util/fv1_geom.h" #include "lib_disc/spatial_disc/disc_util/fvcr_geom.h" #include "lib_disc/spatial_disc/disc_util/hfvcr_geom.h" +#include "lib_disc/spatial_disc/disc_util/fv1FT_geom.h" namespace ug{ namespace NavierStokes{ @@ -102,7 +103,8 @@ class NavierStokesFullUpwind : public INavierStokesUpwind, public NavierStokesUpwindRegister >, public NavierStokesUpwindRegister >, - public NavierStokesUpwindRegister > + public NavierStokesUpwindRegister >, + public NavierStokesUpwindRegisterDim >, dim, NavierStokesFullUpwind > { public: typedef INavierStokesUpwind base_type; @@ -136,6 +138,15 @@ class NavierStokesFullUpwind number vUpShapeSh[maxNumSCVF][maxNumSH], number vUpShapeIp[maxNumSCVF][maxNumSCVF], number vConvLength[maxNumSCVF]); + + /// update of values for DimFV1FTGeometry + template + static void compute(const DimFV1FTGeometry >* geo, + const MathVector vIPVel[maxNumSCVF], + number vUpShapeSh[maxNumSCVF][maxNumSH], + number vUpShapeIp[maxNumSCVF][maxNumSCVF], + number vConvLength[maxNumSCVF]); + }; @@ -220,7 +231,8 @@ template class NavierStokesLinearProfileSkewedUpwind : public INavierStokesUpwind, public NavierStokesUpwindRegister >, - public NavierStokesUpwindRegister > + public NavierStokesUpwindRegister >, + public NavierStokesUpwindRegisterDim >, dim, NavierStokesLinearProfileSkewedUpwind > { public: typedef INavierStokesUpwind base_type; @@ -246,6 +258,15 @@ class NavierStokesLinearProfileSkewedUpwind number vUpShapeSh[maxNumSCVF][maxNumSH], number vUpShapeIp[maxNumSCVF][maxNumSCVF], number vConvLength[maxNumSCVF]); + + /// update of values for DimFV1FTGeometry + template + static void compute(const DimFV1FTGeometry >* geo, + const MathVector vIPVel[maxNumSCVF], + number vUpShapeSh[maxNumSCVF][maxNumSH], + number vUpShapeIp[maxNumSCVF][maxNumSCVF], + number vConvLength[maxNumSCVF]); + }; @@ -256,7 +277,8 @@ class NavierStokesLinearProfileSkewedUpwind template class NavierStokesPositiveUpwind : public INavierStokesUpwind, - public NavierStokesUpwindRegister > + public NavierStokesUpwindRegister >, + public NavierStokesUpwindRegisterDim >,dim, NavierStokesPositiveUpwind > { public: typedef INavierStokesUpwind base_type; @@ -274,6 +296,16 @@ class NavierStokesPositiveUpwind number vUpShapeSh[maxNumSCVF][maxNumSH], number vUpShapeIp[maxNumSCVF][maxNumSCVF], number vConvLength[maxNumSCVF]); + + /// update of values for DimFV1FTGeometry + template + static void compute(const DimFV1FTGeometry >* geo, + const MathVector vIPVel[maxNumSCVF], + number vUpShapeSh[maxNumSCVF][maxNumSH], + number vUpShapeIp[maxNumSCVF][maxNumSCVF], + number vConvLength[maxNumSCVF]); + + }; ///////////////////////////////////////////////////////////////////////////// diff --git a/upwind_interface.h b/upwind_interface.h index 16869e4..d21f6f9 100644 --- a/upwind_interface.h +++ b/upwind_interface.h @@ -88,14 +88,14 @@ class INavierStokesUpwind /// Convection Length number upwind_conv_length(size_t scvf) const { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + // UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); return m_vUpConvLength[scvf]; } /// Convection Length number downwind_conv_length(size_t scvf) const { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + // UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); return m_vDownConvLength[scvf]; } @@ -107,16 +107,18 @@ class INavierStokesUpwind /// upwind shape for corner vel number upwind_shape_sh(size_t scvf, size_t sh) const { - // UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); - // UG_NSUPWIND_ASSERT(sh < m_numSh, "Invalid index"); - return m_vvUpShapeSh[scvf][sh]; + //UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + //UG_NSUPWIND_ASSERT(sh < m_numSh, "Invalid index"); + + return m_vvUpShapeSh[scvf][sh]; } /// upwind shape for corner vel number downwind_shape_sh(size_t scvf, size_t sh) const { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); - UG_NSUPWIND_ASSERT(sh < m_numSh, "Invalid index"); + //UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + //UG_NSUPWIND_ASSERT(sh < m_numSh, "Invalid index"); + return m_vvDownShapeSh[scvf][sh]; } @@ -126,16 +128,18 @@ class INavierStokesUpwind /// upwind shapes for ip vel number upwind_shape_ip(size_t scvf, size_t scvf2) const { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index: " << scvf); - UG_NSUPWIND_ASSERT(scvf2 < m_numScvf, "Invalid index2: " << scvf2); + //UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index: " << scvf); + //UG_NSUPWIND_ASSERT(scvf2 < m_numScvf, "Invalid index2: " << scvf2); + return m_vvUpShapeIp[scvf][scvf2]; } /// upwind shapes for ip vel number downwind_shape_ip(size_t scvf, size_t scvf2) const { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); - UG_NSUPWIND_ASSERT(scvf2 < m_numScvf, "Invalid index"); + //UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + //UG_NSUPWIND_ASSERT(scvf2 < m_numScvf, "Invalid index"); + return m_vvDownShapeIp[scvf][scvf2]; } @@ -175,46 +179,50 @@ class INavierStokesUpwind /// non-const access to upwind shapes for corner vel number& upwind_shape_sh(size_t scvf, size_t sh) { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); - UG_NSUPWIND_ASSERT(sh < m_numSh, "Invalid index"); + //UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + //UG_NSUPWIND_ASSERT(sh < m_numSh, "Invalid index"); + return m_vvUpShapeSh[scvf][sh]; } /// non-const access to upwind shapes for corner vel number& downwind_shape_sh(size_t scvf, size_t sh) { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); - UG_NSUPWIND_ASSERT(sh < m_numSh, "Invalid index"); - return m_vvDownShapeSh[scvf][sh]; + //UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + //UG_NSUPWIND_ASSERT(sh < m_numSh, "Invalid index"); + + return m_vvDownShapeSh[scvf][sh]; } /// non-const access to upwind shapes for ip vel number& upwind_shape_ip(size_t scvf, size_t scvf2) { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); - UG_NSUPWIND_ASSERT(scvf2 < m_numScvf, "Invalid index"); - return m_vvUpShapeIp[scvf][scvf2]; + //UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + //UG_NSUPWIND_ASSERT(scvf2 < m_numScvf, "Invalid index"); + + return m_vvUpShapeIp[scvf][scvf2]; } /// non-const access to upwind shapes for ip vel number& downwind_shape_ip(size_t scvf, size_t scvf2) { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); - UG_NSUPWIND_ASSERT(scvf2 < m_numScvf, "Invalid index"); - return m_vvDownShapeIp[scvf][scvf2]; + //UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + //UG_NSUPWIND_ASSERT(scvf2 < m_numScvf, "Invalid index"); + + return m_vvDownShapeIp[scvf][scvf2]; } /// non-const access to Convection Length number& upwind_conv_length(size_t scvf) { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + //UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); return m_vUpConvLength[scvf]; } /// non-const access to Convection Length number& down_upwind_conv_length(size_t scvf) { - UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); + //UG_NSUPWIND_ASSERT(scvf < m_numScvf, "Invalid index"); return m_vDownConvLength[scvf]; } @@ -321,9 +329,19 @@ set_geometry_type() m_id = id; // set sizes - static TFVGeom& geo = GeomProvider::get(); - m_numScvf = geo.num_scvf(); - m_numSh = geo.num_sh(); + if (TFVGeom::staticLocalData) + { + TFVGeom& geo = GeomProvider::get(); + m_numScvf = geo.num_scvf(); + m_numSh = geo.num_sh(); + } + else // setting data later! + { + // hard code number != maxNumSCVF, since in compute_vel() if not: num_sh() = 4 > 3!! + m_numScvf = dim+2; // maxNumSCVF; + m_numSh = dim+2; // maxNumSH; + } + UG_NSUPWIND_ASSERT(m_numScvf <= maxNumSCVF, "Invalid index"); UG_NSUPWIND_ASSERT(m_numSh <= maxNumSH, "Invalid index"); @@ -412,6 +430,62 @@ class NavierStokesUpwindRegister TImpl& getImpl() {return static_cast(*this);} }; +template +class NavierStokesUpwindRegisterDim +{ +public: + /// Base class + typedef INavierStokesUpwind base_type; + +protected: + static const size_t maxNumSCVF = base_type::maxNumSCVF; + static const size_t maxNumSH = base_type::maxNumSH; + +public: + /// constructor + NavierStokesUpwindRegisterDim() {register_func(Int2Type());} + +private: + void register_func(Int2Type<1>) + { + register_func(); + } + + void register_func(Int2Type<2>) + { + register_func(); + register_func(); + } + + void register_func(Int2Type<3>) + { + register_func(); + register_func(); + register_func(); + register_func(); + } + + template + void register_func() + { + typedef TFVGeom TGeom; + // typedef void (TImpl::*TFunc)( + typedef void (*TFunc)( + const TGeom* obj, + const MathVector vIPVel[maxNumSCVF], + number vUpShapeSh[maxNumSCVF][maxNumSH], + number vUpShapeIp[maxNumSCVF][maxNumSCVF], + number vConvLength[maxNumSCVF]); + + getImpl().template register_update_func(&TImpl::template compute); + } + +protected: + /// access to implementation + TImpl& getImpl() {return static_cast(*this);} +}; + + /// creates upwind based on a string identifier template SmartPtr > CreateNavierStokesUpwind(const std::string& name); From 05962c00693c252d5d0e5853c55f5152d2766acf Mon Sep 17 00:00:00 2001 From: Susanne Date: Mon, 23 Sep 2019 20:41:07 +0200 Subject: [PATCH 2/5] final cleaning NavierStokes --- CMakeLists.txt | 3 +- File | 0 incompressible/CMakeLists.txt | 1 + incompressible/fv1/bnd/inflow_fv1_cutElem.h | 101 + .../fv1/bnd/inflow_fv1_cutElem_impl.h | 87 + .../fv1/moving_particle/Info File 1 | 40 + .../fv1/moving_particle/Info File 2 | 42 + .../fv1/moving_particle/Info File 3 | 6 + .../immersed_bnd_cond_particle.h | 43 +- .../immersed_bnd_cond_particle_impl.h | 287 +-- .../loc_to_glob_mapper_particle.h | 359 ++-- .../loc_to_glob_mapper_particle_impl.h | 1655 ++++++---------- .../loc_to_glob_mapper_particle_tools.h | 330 ---- .../fv1/moving_particle/meanID_tools.h | 1732 ----------------- .../fv1/moving_particle/moving_particle.h | 381 ++-- .../moving_particle/moving_particle_impl.h | 871 ++++----- .../moving_particle/moving_particle_tools.h | 308 +-- incompressible/fv1/navier_stokes_fv1.cpp | 112 +- ..._FV1.cpp => navier_stokes_fv1_cutElem.cpp} | 198 +- .../fv1/navier_stokes_fv1_cutElem.h | 587 ++++++ incompressible/fv1/register_fv1.cpp | 46 +- incompressible/fv1/stabilization.h | 4 +- .../two_phase_flow/interface_handler_2pf.h | 15 +- .../interface_handler_2pf_impl.h | 67 +- .../two_phase_flow/loc_to_glob_mapper_2pf.h | 10 +- .../loc_to_glob_mapper_2pf_impl.h | 45 +- .../fv1/two_phase_flow/two_phase_flow.h | 38 +- .../fv1/two_phase_flow/two_phase_flow_impl.h | 31 +- .../particle_laden_flow_plugin Kopie.cpp | 414 ---- incompressible/particle_laden_flow_plugin.cpp | 83 +- .../particle_laden_flow_plugin_origJonas.cpp | 414 ---- upwind.cpp | 33 + upwind.h | 11 +- 33 files changed, 2705 insertions(+), 5649 deletions(-) delete mode 100644 File create mode 100644 incompressible/fv1/bnd/inflow_fv1_cutElem.h create mode 100644 incompressible/fv1/bnd/inflow_fv1_cutElem_impl.h create mode 100644 incompressible/fv1/moving_particle/Info File 1 create mode 100644 incompressible/fv1/moving_particle/Info File 2 create mode 100644 incompressible/fv1/moving_particle/Info File 3 delete mode 100644 incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_tools.h delete mode 100644 incompressible/fv1/moving_particle/meanID_tools.h rename incompressible/fv1/{navier_stokes_fv1_FV1.cpp => navier_stokes_fv1_cutElem.cpp} (89%) create mode 100644 incompressible/fv1/navier_stokes_fv1_cutElem.h delete mode 100644 incompressible/particle_laden_flow_plugin Kopie.cpp delete mode 100644 incompressible/particle_laden_flow_plugin_origJonas.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 67db2db..5ed929e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,8 @@ set(SOURCES navier_stokes_base.cpp incompressible/incompressible_navier_stokes_base.cpp incompressible/fv1/navier_stokes_fv1.cpp - incompressible/fe/navier_stokes_fe.cpp + incompressible/fv1/navier_stokes_fv1_cutElem.cpp + incompressible/fe/navier_stokes_fe.cpp incompressible/fvcr/navier_stokes_fvcr.cpp incompressible/fv/navier_stokes_fv.cpp diff --git a/File b/File deleted file mode 100644 index e69de29..0000000 diff --git a/incompressible/CMakeLists.txt b/incompressible/CMakeLists.txt index 3a4c3f5..c5c1450 100644 --- a/incompressible/CMakeLists.txt +++ b/incompressible/CMakeLists.txt @@ -51,6 +51,7 @@ set(SOURCES ../navier_stokes_base.cpp incompressible_navier_stokes_base.cpp fv1/navier_stokes_fv1.cpp + fv1/navier_stokes_fv1_cutElem.cpp fe/navier_stokes_fe.cpp fvcr/navier_stokes_fvcr.cpp fv/navier_stokes_fv.cpp diff --git a/incompressible/fv1/bnd/inflow_fv1_cutElem.h b/incompressible/fv1/bnd/inflow_fv1_cutElem.h new file mode 100644 index 0000000..f62233a --- /dev/null +++ b/incompressible/fv1/bnd/inflow_fv1_cutElem.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2013: G-CSC, Goethe University Frankfurt + * Author: Andreas Vogel + * + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#ifndef __H__UG__NAVIER_STOKES__INCOMPRESSIBLE__FV1__BND__INFLOW_FV1_CUT_ELEM__ +#define __H__UG__NAVIER_STOKES__INCOMPRESSIBLE__FV1__BND__INFLOW_FV1_CUT_ELEM__ + +#include "../../bnd/inflow_base.h" +#include "../navier_stokes_fv1_cutElem.h" + +#include "lib_disc/spatial_disc/elem_disc/neumann_boundary/neumann_boundary_base.h" +#include "lib_disc/spatial_disc/constraints/dirichlet_boundary/lagrange_dirichlet_boundary.h" +#include "lib_disc/spatial_disc/elem_disc/neumann_boundary/fv1/neumann_boundary_fv1.h" + +namespace ug{ +namespace NavierStokes{ + +template < typename TDomain, typename TAlgebra> +class NavierStokesInflowFV1_cutElem + : public NavierStokesInflowBase +{ + private: + static const int dim = TDomain::dim; + + public: + + /// returns the number of element discs + virtual size_t num_elem_disc() const {return 1;} + + /// returns the element disc + virtual SmartPtr > elem_disc(size_t i) {return m_spNeumannDisc;} + + /// returns the number of constraints + virtual size_t num_constraint() const {return 1;} + + /// returns an element disc + virtual SmartPtr > constraint(size_t i) {return m_spDirichletConstraint;} + + public: + /// Constructor + NavierStokesInflowFV1_cutElem(SmartPtr< NavierStokesFV1_cutElem > spMaster) + : m_spNeumannDisc(new NeumannBoundaryFV1(spMaster->symb_fcts()[dim].c_str())), + m_spDirichletConstraint(new DirichletBoundary), + m_spMaster(spMaster) // copy constructor not defined for _cutElem? + { + const std::vector& vFctName = m_spMaster->symb_fcts(); + + if(vFctName.size() != TDomain::dim + 1) + UG_THROW("NavierStokesInflow::set_functions: This Boundary " + "Condition works on exactly dim+1 (velocity+pressure) " + "components, but "<, dim> > user, const char* subsetsBND); + + protected: + /// neumann disc for pressure equation + SmartPtr > m_spNeumannDisc; + + /// dirichlet disc for velocity components + SmartPtr > m_spDirichletConstraint; + + /// The master discretization: + SmartPtr< NavierStokesFV1_cutElem > m_spMaster; +}; + +} // namespace NavierStokes +} // end namespace ug + +#include "inflow_fv1_cutElem_impl.h" + +#endif /* __H__UG__NAVIER_STOKES__INCOMPRESSIBLE__FV1__BND__INFLOW_FV1_CUT_ELEM__ */ diff --git a/incompressible/fv1/bnd/inflow_fv1_cutElem_impl.h b/incompressible/fv1/bnd/inflow_fv1_cutElem_impl.h new file mode 100644 index 0000000..21e3132 --- /dev/null +++ b/incompressible/fv1/bnd/inflow_fv1_cutElem_impl.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2013: G-CSC, Goethe University Frankfurt + * Author: Andreas Vogel + * + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#ifndef __H__UG__NAVIER_STOKES__BND__INFLOW_FV1_CUT_ELEM_IMPL__ +#define __H__UG__NAVIER_STOKES__BND__INFLOW_FV1_CUT_ELEM_IMPL__ + +#include "inflow_fv1_cutElem.h" +#include "lib_disc/spatial_disc/elem_disc/neumann_boundary/fv1/neumann_boundary_fv1.h" + +namespace ug{ +namespace NavierStokes{ +/* +template +NavierStokesInflowFV1_cutElem:: +NavierStokesInflowFV1_cutElem(SmartPtr< NavierStokesFV1_cutElem > spMaster) + : m_spNeumannDisc(new NeumannBoundaryFV1(spMaster->symb_fcts()[dim].c_str())), + m_spDirichletConstraint(new DirichletBoundary), + m_spMaster(spMaster) +{ + const std::vector& vFctName = m_spMaster->symb_fcts(); + + if(vFctName.size() != TDomain::dim + 1) + UG_THROW("NavierStokesInflow::set_functions: This Boundary " + "Condition works on exactly dim+1 (velocity+pressure) " + "components, but "< +void NavierStokesInflowFV1_cutElem:: +add(SmartPtr, dim> > user, const char* subsetsBND) +{ + const std::vector& vFctName = m_spMaster->symb_fcts(); + if(vFctName.empty()) + UG_THROW("NavierStokesInflow::add: Symbolic names for" + " velocity and pressure not set. Please set them first."); + + std::string innerSubsets; + for(size_t s = 0; s < m_spMaster->symb_subsets().size(); ++s){ + if(s > 0) innerSubsets.append(","); + innerSubsets.append(m_spMaster->symb_subsets()[s]); + } + + + m_spNeumannDisc->add(user, subsetsBND, innerSubsets.c_str()); + + std::string velNames; + for(int i=0;i0) velNames.append(","); + velNames.append(vFctName[i]); + } + m_spDirichletConstraint->add(user.template cast_dynamic, dim> >(), velNames.c_str(), subsetsBND); +} + +} // namespace NavierStokes +} // end namespace ug + +#endif /* __H__UG__NAVIER_STOKES__BND__INFLOW_FV1_CUT_ELEM_IMPL__ */ diff --git a/incompressible/fv1/moving_particle/Info File 1 b/incompressible/fv1/moving_particle/Info File 1 new file mode 100644 index 0000000..7704b16 --- /dev/null +++ b/incompressible/fv1/moving_particle/Info File 1 @@ -0,0 +1,40 @@ +/* Info File for 'MovingParticle' class: */ + +The 'MovingParticle' class enables the simulation of moving particles in a fluid. Detailed descriptions of the mathematical theory and numerical simulations can be found in [1] and [2]. +The interaction between the fluid and the particles takes place at the interface of the particles, which acts therefore as an immersed interface for the fluid. Consequently, the 'MovingParticle' class implements a derivation of the 'ImmersedInterface' class. It therefore contains all the components of an 'ImmersedInterface' class implemented according to the necessities for moving particles. Those are explained in more detail in the according class types. + + + +The special requirements for a moving particle immersed interface implementation are the following: + +(1) Each particle is described as a rigid motion, i.e. by its two components: the translational and rotational velocity. As a consequence, in the discrete scheme each particle is described by the DoFs for its translational and rotational velocities. Those can be stored in two geometrical nodes of the mesh. Their location within each particle gets defined during an initialisation phase. Most of the nodes within the particles are therefore NO DoFs for the particle, beside the designated nodes (named 'transInd' and 'rotInd' for the associated global indices). + +(2) Furthermore, a particle usually covers more than one (local) finite element. Since the solution for the particle velocities is coupled with and need to be known for all surrounding fluid DoFs, the DoFs need to be accessible on a GLOBAL scale as well. The assigned global indices ('transInd' and 'rotInd') for the particle DoFs need to be accessible globally. Furthermore, the initialization of the interfaces of the particles inherits the collection of all cut elements. + + +The two central methods called during the initialisation (called via the 'init()' of the associated 'CutElementHandler') are: + +---> update_interface_data(): computes all cut elements +---> update_global_indices(): defines the nodes and indices within a particle, which act as particle DoFs + + +Further remarks: + +- Most of the nodes within the particles are NO DoFs for the particle. + +- During the movement of a particle in time, nodes that were part of the particle can get part of the fluid in the next time step. Since they were no designated DoFs within the particle they similarly did not contain the solution. A 'filling' of these so called 'freed' nodes need to be performed during the (geometrical) update of the particle interfaces. + +- During the local assembling of the defect, the solution for the translational or rotational components of the particle velocity will be overwritten with the physical particle velocity (a combination of boths). Before and after these computations the particle solution needs to be transfered back and forth between local and global data structures for all later assembling. + + + + +[1] Hoellbacher S., Wittum G.: + "Rotational test spaces for a fully-implicit FVM and FEM for the DNS of fluid-particle interaction" + Journal of Computational Physics, vol. 393, (2019), pp. 186–213 + open access link: https://authors.elsevier.com/sd/article/S0021999119303298 + DOI: https://doi.org/10.1016/j.jcp.2019.05.004 + +[2] Hoellbacher S., Wittum G.: + "Gradient-consistent enrichment of finite element spaces for the DNS of fluid-particle interaction." + submitted to Jounal of Computational Physics diff --git a/incompressible/fv1/moving_particle/Info File 2 b/incompressible/fv1/moving_particle/Info File 2 new file mode 100644 index 0000000..fd54cbe --- /dev/null +++ b/incompressible/fv1/moving_particle/Info File 2 @@ -0,0 +1,42 @@ +/* Info File for 'ParticleMapper' class: */ + +The 'ParticleMapper' class handles the mapping from the locally computed data (stiffnes matrix, defect) to the global algebra. + +The 2 main components are: + +(1) Mapping of the local indices, which are associated to the particle DoFs to their global indices. +(2) Performing the cross product multiplication for local indices associated to the rotational velocity DoFs. + + +Important methods: + +---> the hierarchy + + 'add_local_mat_to_global()' ---> 'add_local_mat_to_global_interface()' ---> 'add_local_mat_to_global_FT()' + + forwards the adapted mapping for the cut elements + +---> modify_LocalData(): resizes the local data (LocalMatrix or LocalVecor) BEFORE starting the assembling on the element. It is called during the elements discretisation loop (see elem_disc_assemble_util()). + +---> modify_GlobalSol(): writes the particle velocities stored in its designated global indices to own data in order to protect it from being overwritting in the following local assembling process and provide global access. + + + + +The flat-top ansatz space: + +On a cut element, local couplings will be computed for all the intersection points of the interface with the edges of the cut element. The mapping of these couplings to its associated global indices finally defines the property of the underlying finite element space: + +Case 1: Each coupling is mapped to its own, designated global index, i.e. DoF. The resulting space will be the usual finite element space w.r.t. the interface adaped grid. It therefore contains additional nodes along the interface and (virtually) consists of cut elements and original elements. + +Case 2: The local coupling of an intersection point is mapped onto the global index of the original node, which lies accross the interface, but on the corner of the same element. The resulting finite element space will potentially be smaller than the one of the cut element, since two and more (in 3d) intersection points can share the same node accross the interface. The resulting space is a so called "flat top" space, since it results in piecewise constant solutions along the connecting hyperplane between these intersection points. + + +The 'ParticleMapper' class is of type case 2: +It maps all couplings of intersection points to the same translational (and in analogy to the rotational) global index. Therefore, the 'ParticleMapper' is a flat-top mapper. + +In contrast, the 'DiffusionInterfaceMapper' is of type case 1: +In particular, it is a tow-sided mapper and the resulting space is an interface adapted space. + + + diff --git a/incompressible/fv1/moving_particle/Info File 3 b/incompressible/fv1/moving_particle/Info File 3 new file mode 100644 index 0000000..ec52e24 --- /dev/null +++ b/incompressible/fv1/moving_particle/Info File 3 @@ -0,0 +1,6 @@ +/* Info File for 'ParticleBndCond' class: */ + +Assemlbes the stresses on the particle interface. For that, the common forces will be assembled as for usual boundary faces, BUT on the according boundary faces which were computed for the cut element during the local update of the element. + +The boundary faces of the cut elements got stored into the 'm_vBF' member of the 'InterfaceHandlerLocalParticle' class. + diff --git a/incompressible/fv1/moving_particle/immersed_bnd_cond_particle.h b/incompressible/fv1/moving_particle/immersed_bnd_cond_particle.h index 6ae16cf..671f81d 100644 --- a/incompressible/fv1/moving_particle/immersed_bnd_cond_particle.h +++ b/incompressible/fv1/moving_particle/immersed_bnd_cond_particle.h @@ -35,9 +35,19 @@ class ParticleBndCond : public IInterfaceBndCond /// call base class constructor - ParticleBndCond(SmartPtr > spMaster, + ParticleBndCond(SmartPtr > spMaster, SmartPtr > localHandler); + + /// destructor + virtual ~ParticleBndCond(){}; + + /////////////////////////////////////////////////////////////////////////////// + /// + /// base class methods + /// + /////////////////////////////////////////////////////////////////////////////// + public: /// type of trial space for each function used void prepare_setting(const std::vector& vLfeID, bool bNonRegularGrid); @@ -61,12 +71,15 @@ class ParticleBndCond : public IInterfaceBndCond void add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]); + /// helper method called by 'add_jac_A_elem()' void add_jac_A_elem_Quadri_for2(LocalMatrix& J, const LocalVector locU); /// adds the stiffness part to the local defect template void add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]); + + /// helper method called by 'add_def_A_elem()' void add_def_A_elem_Quadri_for2(LocalVector& locD, const LocalVector locU); void add_quadri_to_defect(LocalVector& d, const LocalVector& quadriD); @@ -82,38 +95,47 @@ class ParticleBndCond : public IInterfaceBndCond void add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoords[]); + // computes contributions to local stiffness matrix due to the stresses on the particle boundary void diffusive_flux_Jac(const size_t ip, const interfaceBF& bf, LocalMatrix& J, const LocalVector& u); void diffusive_flux_Jac_for2(const size_t ip, const interfaceBF& bf, LocalMatrix& J, const LocalVector& u); void diffusive_flux_Jac_rot(const size_t ip, const interfaceBF& bf, LocalMatrix& J, const LocalVector& u, number importDensity); + // computes contributions to local defect due to the stresses on the particle boundary void diffusive_flux_defect(const size_t ip, const interfaceBF& bf, LocalVector& d, const LocalVector& u); void diffusive_flux_defect_rot(const size_t ip, const interfaceBF& bf, LocalVector& d, const LocalVector& u); + // reset entries for the momentum equations for interface-corner: + // set entries in local data to zero BEFORE adding the computed contributions from the boundary condition void remove_equations(LocalVector& d, std::vector vFctID, std::vector vDofID); void remove_equations(LocalMatrix& J, std::vector vFctID, std::vector vDofID); + // gets the current index of the particle, which cuts the current element; + // stored in 'InterfaceHandlerLocalParticle' int get_prtIndex() { return m_spInterfaceHandlerLocal->get_prtIndex(); } number get_density(int prtIndex) { return m_spInterfaceHandlerLocal->get_density(prtIndex); } - number get_density_fluid() { return m_spInterfaceHandlerLocal->get_density_fluid(); } - number get_kinVisc_fluid() { return m_spInterfaceHandlerLocal->get_kinVisc_fluid(); } + number get_density_fluid() { return m_spInterfaceHandlerLocal->get_density_fluid(); } + number get_kinVisc_fluid() { return m_spInterfaceHandlerLocal->get_kinVisc_fluid(); } + // method called by 'ParticleMapper' class for acces to boundary conditions, assembled by this class void copy_local_couplings_jac() - { m_spInterfaceHandlerLocal->set_local_couplings_jac(rotJ_ind, rotJ_rot); } + { m_spInterfaceHandlerLocal->set_local_couplings_jac(rotJ_ind, rotJ_rot); } void copy_local_couplings_def() - { m_spInterfaceHandlerLocal->set_local_couplings_def(rotD); } + { m_spInterfaceHandlerLocal->set_local_couplings_def(rotD); } void write_QuadriSol(const LocalVector origU); - /// remaps entries for Quadri+Tri-combination of CUT_BY_2_INTERFACE element + /// remaps entries for Quadri+Tri-combination of CUT_BY_2_INTERFACE element size_t remap_for2(size_t dof); - /// destructor - ~ParticleBndCond(){}; + + /////////////////////////////////////////////////////////////////////////////// + /// class member + /////////////////////////////////////////////////////////////////////////////// protected: // master element disc - SmartPtr > m_spMaster; + SmartPtr > m_spMaster; // member from base class SmartPtr > m_spInterfaceHandlerLocal; @@ -123,9 +145,6 @@ class ParticleBndCond : public IInterfaceBndCond LocalMatrix rotJ_rot; LocalVector rotD; - /// Boundary integration points of the viscosity and the density -// std::vector > m_vLocIP; -// std::vector > m_vGloIP; protected: void register_all(bool bHang); diff --git a/incompressible/fv1/moving_particle/immersed_bnd_cond_particle_impl.h b/incompressible/fv1/moving_particle/immersed_bnd_cond_particle_impl.h index 8bf7aa3..13ec95b 100644 --- a/incompressible/fv1/moving_particle/immersed_bnd_cond_particle_impl.h +++ b/incompressible/fv1/moving_particle/immersed_bnd_cond_particle_impl.h @@ -19,7 +19,7 @@ namespace NavierStokes{ // see 'no_normal_stress_outflow.cpp': template ParticleBndCond:: -ParticleBndCond(SmartPtr > spMaster, +ParticleBndCond(SmartPtr > spMaster, SmartPtr > localHandler) : IInterfaceBndCond(spMaster->symb_fcts(), spMaster->symb_subsets(), localHandler), m_spMaster(spMaster), @@ -82,15 +82,10 @@ diffusive_flux_Jac_rot(const size_t ip, const interfaceBF& bf, LocalMatrix& J, c MathVector angularVel; RotIndMat = 0.0; RotRotMat = 0.0; angularVel = 0.0; - UG_LOG("*RotIndMat = " << RotIndMat << "\n"); - UG_LOG("*RotRotMat = " << RotRotMat << "\n"); - UG_LOG("*angularVel = " << angularVel << "\n"); - MathMatrix rotationMatIP_transposed = m_spInterfaceHandlerLocal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_ip(bf.node_id())); Transpose(rotationMatIP_transposed); - UG_LOG("start sh-loop for = " << ip << "\n"); - + for(size_t sh = 0; sh < bf.num_sh(); ++sh) // loop shape functions { // 1. Compute the total flux @@ -110,33 +105,22 @@ diffusive_flux_Jac_rot(const size_t ip, const interfaceBF& bf, LocalMatrix& J, c // 2. compute r x [\sigma(u)]*n // => compute local couplings between rotation and translation/fluid MatMultiply(RotIndMat, rotationMatIP_transposed, diffFlux); - UG_LOG("rotationMatIP_transposed " << rotationMatIP_transposed << "\n"); - UG_LOG(". diffFlux " << diffFlux << "\n"); - UG_LOG("= RotIndMat " << RotIndMat << "\n"); // 3. compute r x [\sigma(w x r)]*n if ( m_spInterfaceHandlerLocal->lies_onInterface(sh) ) { - UG_LOG("sh = " << sh << "on interface\n"); - UG_LOG("rotationMatIP_transposed " << rotationMatIP_transposed << "\n"); - // 3.1 compute r x [...]*n MatMultiply(RotRotMat, rotationMatIP_transposed, diffFlux); // 3.2 compute [\sigma(w x r)]*n MathMatrix rotationMatSH = m_spInterfaceHandlerLocal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(sh)); MatMultiply(RotRotMat, RotRotMat, rotationMatSH); - UG_LOG("rotationMatSH " << rotationMatSH << "\n"); - + // 3.3 compute (w x r)*n for continuity equation // transpose in order to multiply from left: // n^T*rotationMatSH = rotationMatSH^T*n Transpose(rotationMatSH); MatVecMult(angularVel, rotationMatSH, bf.normal()); - UG_LOG("transposed rotationMatSH " << rotationMatSH << "\n"); - UG_LOG("bf.normal() " << bf.normal() << "\n"); - UG_LOG("__angularVel(2. komp = 0?? " << angularVel << "\n"); - } // 4. Change sign, since force acts onto particle in inverse direction: @@ -164,18 +148,9 @@ diffusive_flux_Jac_rot(const size_t ip, const interfaceBF& bf, LocalMatrix& J, c VecScale(angularVel, angularVel, bf.shape(sh)); for (size_t d2 = 0; d2 < (size_t)dim; ++d2) rotJ_ind(_P_, bf.node_id(), d2, sh) += angularVel[d2]; - - UG_LOG("angularVel(2. komp = 0?? " << angularVel << "\n"); - } - UG_LOG("RotIndMat " << RotIndMat << "\n"); - UG_LOG("RotRotMat " << RotRotMat << "\n"); - - if ( m_spInterfaceHandlerLocal->m_vInterfaceID[0] == m_spInterfaceHandlerLocal->m_vInterfaceID[1]) - UG_THROW("end sh-loop for = " << ip << "\n"); - } @@ -212,7 +187,6 @@ diffusive_flux_Jac(const size_t ip, const interfaceBF& bf, LocalMatrix& J, const for(size_t d1 = 0; d1 < (size_t)dim; ++d1) for(size_t d2 = 0; d2 < (size_t)dim; ++d2){ J(d1, bf.node_id(), d2, sh) += diffFlux (d1, d2); - // if ( sh < 2 ) UG_LOG("bf.node_id(): " << bf.node_id() << "sh: " << sh << ": diff_flux added: " << diffFlux (d1, d2) << "\n"); } // 5. Add pressure term to local Jacobian @@ -233,8 +207,8 @@ add_jac_A_elem_Quadri_for2(LocalMatrix& J, const LocalVector locU) std::vector& vBF = m_spInterfaceHandlerLocal->get_boundary_faces(); if ( vBF.size() != 4 ) - UG_THROW("in 'ParticleBndCond::add_jac_A_elem_Quadri_for2(): vBF.size() should be 4 but is " << vBF.size() << "\n"); - + UG_THROW("in 'ParticleBndCond::add_jac_A_elem_Quadri_for2(): vBF.size() should be 4 but is " + << vBF.size() << "\n"); // get density number importDensity = fluidDensity->value(0, 0); @@ -264,22 +238,8 @@ add_jac_A_elem_Quadri_for2(LocalMatrix& J, const LocalVector locU) * importDensity; } - if ( 1 ) - { - UG_LOG("----- ip = " << ip << "------\n"); - UG_LOG("bf.nodeID: " << bf.node_id() << "\n"); - UG_LOG(" bf.normal(): " << bf.normal() << "\n"); - UG_LOG("bf.vGloPos[0: " << bf.global_corner(0) << "\n"); - UG_LOG("bf.vGloPos[1]: " << bf.global_corner(1) << "\n"); - } } // end vBF-loop - if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 4 ) - { - UG_LOG("J = " << J << "\n"); - UG_LOG("J.num_all_row_dof(0): " << J.num_all_row_dof(0) << "\n"); - } - } @@ -304,14 +264,6 @@ remap_for2( size_t dof) if ( dof == m_spInterfaceHandlerLocal->m_vNOInterfaceID[0] ) return 4; - UG_LOG("m_spInterfaceHandlerLocal->m_vInterfaceID[0]: " << m_spInterfaceHandlerLocal->m_vInterfaceID[0] << "\n"); - UG_LOG("m_spInterfaceHandlerLocal->m_vInterfaceID[1]: " << m_spInterfaceHandlerLocal->m_vInterfaceID[1] << "\n"); - - UG_LOG("m_spInterfaceHandlerLocal->m_vQuadriOrigID[0]: " << m_spInterfaceHandlerLocal->m_vQuadriOrigID[0] << "\n"); - UG_LOG("m_spInterfaceHandlerLocal->m_vQuadriOrigID[2]: " << m_spInterfaceHandlerLocal->m_vQuadriOrigID[2] << "\n"); - - UG_LOG("m_spInterfaceHandlerLocal->m_vNOInterfaceID[0]: " << m_spInterfaceHandlerLocal->m_vNOInterfaceID.size() << "\n"); - if ( m_spInterfaceHandlerLocal->m_vInterfaceID[0] == m_spInterfaceHandlerLocal->m_vQuadriOrigID[0] ) { if ( dof == m_spInterfaceHandlerLocal->m_vInterfaceID[0] ) @@ -337,10 +289,13 @@ template void ParticleBndCond:: add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) { - ElementModus elemModus = m_spInterfaceHandlerLocal->get_element_modus(elem); // computed via 'compute_element_modus()' during 'update_marker()' + ElementModus elemModus = m_spInterfaceHandlerLocal->get_element_modus(elem); + // --> computed via 'compute_element_modus()' during 'update_interface_data()' + +//////////////////////////////////////////////////////////////////////////////// +// (A) Remove local impuls equations for interface-corners +//////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // Remove local impuls equations for interface-corners if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling { @@ -364,26 +319,21 @@ add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat } +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// (B) If CUT_BY_2_INTERFACE or StdFVAssembling, no additional interface stresses will be computed +// => map existing entries +//////////////////////////////////////////////////////////////////////////////// + if ( elemModus == CUT_BY_2_INTERFACE && ! m_spInterfaceHandlerLocal->StdFV_assembling() ) { - - for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vNOInterfaceID.size(); ++i ) - UG_THROW("m_vNOInterfaceID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vNOInterfaceID[i] << "\n"); - for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vInterfaceID.size(); ++i ) - UG_LOG("m_vInterfaceID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vInterfaceID[i] << "\n"); - for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vQuadriOrigID.size(); ++i ) - UG_LOG("m_vQuadriOrigID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vQuadriOrigID[i] << "\n"); - if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) { size_t copyID = m_spInterfaceHandlerLocal->m_vNOInterfaceID[0]; const LocalIndices& ind = m_spInterfaceHandlerLocal->get_local_indices(); LocalMatrix buffJ; buffJ.resize(ind); buffJ = 0; - UG_LOG("1 buffJ = " << buffJ << "\n"); - + copy_and_reset(buffJ,J); - UG_LOG("2 buffJ = " << buffJ << "\n"); - + // remap impulse equation for inside node for(size_t j = 0; j < dim; ++j) @@ -397,20 +347,12 @@ add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat for(size_t fct = 0; fct < J.num_all_row_fct(); ++fct) for(size_t dof2 = 0; dof2 < 3; ++dof2) J(_P_, remap_for2(dof1), fct, remap_for2(dof2)) = buffJ(_P_, dof1, fct, dof2); - - } // case == 4: all entries (also for pressure eq) will be written newly, since only boundary faces are relevant // => during remove_equations() only velocity equations were removed! - - //if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) - // remap_inside_equation(J, vFctID, vDoFID); - //else if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 4 ) J = 0.0; - //else - // UG_THROW("in ParticleBndCond::add_def_A_elem(): wrong amount of interface.size() for CUT_BY_2_INTERFACE: " << m_spInterfaceHandlerLocal->interface_id_all().size() << " ( should be 2!)\n"); const LocalIndices& ind = m_spInterfaceHandlerLocal->get_local_indices(); @@ -424,23 +366,19 @@ add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat else UG_THROW("in ParticleBndCond::add_def_A_elem(): wrong amount of interface.size() for CUT_BY_2_INTERFACE: " << m_spInterfaceHandlerLocal->interface_id_all().size() << " ( should be 2!)\n"); - if ( 0 ) //m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) - UG_THROW("J = \n" << J << "\n"); - - UG_LOG("end CUT_BY_2_INTERFACE\n"); - return; } //////////////////////////////////////////////////////////////////////////////// -// see 'ParticleFlatTop::add_jac_A_elem_interface()' +// (C) For CUT_BY_INTERFACE: compute stresses on inner boundary faces 'vBF' +// via 'diffusive_flux_Jac()' and add the to local stiffness matrix //////////////////////////////////////////////////////////////////////////////// // Loop the boundary faces for new impuls equations // --> IFF INSIDE_DOM: vBF.size() = 0 ;-) SmartPtr > fluidDensity = m_spMaster->density(); std::vector& vBF = m_spInterfaceHandlerLocal->get_boundary_faces(); - + // initialize data (written during call of 'diffusive_flux_Jac()': LocalIndices ind = u.get_indices(); rotJ_ind.resize(ind); rotJ_ind = 0.0; @@ -448,7 +386,6 @@ add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat for(size_t ip = 0; ip < vBF.size(); ++ip) { - interfaceBF bf = vBF[ip]; if ( fluidDensity->value(0, ip) != fluidDensity->value(1, ip) ) @@ -460,12 +397,6 @@ add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat // The momentum equation: if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling diffusive_flux_Jac(ip, bf, J, u); - // diffusive_flux_Jac_rot(ip, bf, J, u, importDensity); - - // scale with deltaT ( = 1.0 for non-time-dependent) - // buffJ *= deltaT; - // ToDo --> NOT necessary, since add_def_A_elem() will be multiplied by 'dt' - // during elem_dis_assemble_util.h ??? // The continuity equation if ( 1 ) //! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling @@ -534,7 +465,6 @@ diffusive_flux_defect_rot(const size_t ip, const interfaceBF& bf, LocalVector& d { MathVector radialCo; VecSubtract(radialCo, m_spInterfaceHandlerLocal->corner(sh), center); - UG_LOG("m_spInterfaceHandlerLocal->corner(sh) = " << m_spInterfaceHandlerLocal->corner(sh) << "\n"); MathMatrix rotationMatCo = m_spInterfaceHandlerLocal->get_rotationMat(radialCo); // set solution number sol = transSol[d1]; @@ -650,8 +580,6 @@ add_def_A_elem_Quadri_for2(LocalVector& locD, const LocalVector locU) if ( vBF.size() != 4 ) UG_THROW("in 'ParticleBndCond::add_def_A_elem_Quadri_for2(): vBF.size() should be 4 but is " << vBF.size() << "\n"); - UG_LOG("vBF.size(): " << vBF.size() << "\n"); - // get density number importDensity = fluidDensity->value(0, 0); if ( fluidDensity->value(0, 0) != fluidDensity->value(1, 0) ) @@ -690,14 +618,11 @@ template void ParticleBndCond:: write_QuadriSol(const LocalVector origU) { - UG_LOG("start write_QuadriSol\n"); - + // initialize data LocalIndices ind = origU.get_indices(); LocalVector quadriU; - UG_LOG("1 start write_QuadriSol\n"); - if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) { for(size_t fct = 0; fct < ind.num_fct(); ++fct) @@ -708,18 +633,13 @@ write_QuadriSol(const LocalVector origU) } quadriU.resize(ind); - UG_LOG("2 start write_QuadriSol\n"); - // A. remap solution (velocity AND pressure!) of inside node if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) { size_t copyID = m_spInterfaceHandlerLocal->m_vNOInterfaceID[0]; for(size_t fct = 0; fct < dim+1; ++fct) - {quadriU(fct,4) = origU(fct,copyID); - UG_LOG("origU(fct,copyID) = " << origU(fct,copyID) << "\n");} - } - - UG_LOG("3 start write_QuadriSol: quadriU \n" << quadriU << "\n"); + quadriU(fct,4) = origU(fct,copyID); + } if ( m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) { @@ -727,10 +647,6 @@ write_QuadriSol(const LocalVector origU) UG_THROW("m_vNOInterfaceID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vNOInterfaceID[i] << "\n"); } - for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vInterfaceID.size(); ++i ) - UG_LOG("m_vInterfaceID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vInterfaceID[i] << "\n"); - for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vQuadriOrigID.size(); ++i ) - UG_LOG("m_vQuadriOrigID[" << i << "]: " << m_spInterfaceHandlerLocal->m_vQuadriOrigID[i] << "\n"); std::vector testV; for(size_t dof = 0; dof < 4; ++dof) @@ -741,32 +657,22 @@ write_QuadriSol(const LocalVector origU) for(size_t dof = 0; dof < 4; ++dof) { quadriU(fct,dof) = testV[m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]]; //origU(fct,m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]); - UG_LOG("quadriU(fct,dof): " << quadriU(fct,dof) << "\n"); - UG_LOG("testV[" << m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof] << "]: " << testV[m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]] << "\n"); - } - - UG_LOG("start write_QuadriSol: quadriU = \n" << quadriU << "\n"); - UG_THROW("4 start write_QuadriSol\n"); + } + // C. write velocities of the 2 particles: MathVector transSol1 = m_spInterfaceHandlerLocal->get_transSol(0, 0); MathVector rotSol1 = m_spInterfaceHandlerLocal->get_rotSol(0, 0); MathVector transSol2 = m_spInterfaceHandlerLocal->get_transSol(1, 0); MathVector rotSol2 = m_spInterfaceHandlerLocal->get_rotSol(1, 0); - UG_LOG("transSol1 = " << transSol1 << "\n"); - UG_LOG("transSol2 = " << transSol2 << "\n"); - UG_LOG("rotSol1 = " << rotSol1 << "\n"); - UG_LOG("rotSol2 = " << rotSol2 << "\n"); - // resize local data as done during 'modify_LocalSol' // --> but there with num_co = 3 for the Triangle with inside node! for(size_t fct = 0; fct < ind.num_fct(); ++fct) for(size_t dof = 0; dof < 4; ++dof) { MathMatrix rotationMatCo = m_spInterfaceHandlerLocal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(dof)); - UG_LOG("write_QuadriSol: radial(" << dof << ": " << m_spInterfaceHandlerLocal->radial_at_co(dof) << "\n"); - + // write solution of particle with prtIndex = 0: if ( dof < 2 ) { @@ -782,33 +688,20 @@ write_QuadriSol(const LocalVector origU) quadriU(fct,dof) += rotationMatCo[fct][d]*rotSol2[d]; } } - - - UG_LOG("after write_QuadriSol: quadriU = \n" << quadriU << "\n"); - } + + template void ParticleBndCond:: add_quadri_to_defect(LocalVector& d, const LocalVector& quadriD) { -// const LocalIndices& ind = quadriD.get_indices(); - UG_LOG("START add_quadri_to_defect \n"); - - for ( size_t i = 0; i < m_spInterfaceHandlerLocal->m_vQuadriOrigID.size(); ++i ) - UG_LOG("m_vOrig[" << i << "] = " << m_spInterfaceHandlerLocal->m_vQuadriOrigID[i] << "\n"); - - UG_LOG("d: \n" << d << "\n"); - UG_LOG("quadriD: \n" << quadriD << "\n"); + for(size_t fct=0; fct < quadriD.num_all_fct(); ++fct) { - UG_LOG("fct = " << fct << "quadriD.num_all_dof(fct) = " << quadriD.num_all_dof(fct) << "\n"); - for(size_t dof=0; dof < quadriD.num_all_dof(fct); ++dof) { - UG_LOG("0 -> dof = " << dof << "\n"); - - if ( quadriD.value(fct,dof) != quadriD.value(fct,dof)) + if ( quadriD.value(fct,dof) != quadriD.value(fct,dof) ) UG_THROW("NAN in 'add_quadri_to_defect()'!...\n"); bool isPrtNode = m_spInterfaceHandlerLocal->lies_onInterface(dof); @@ -816,11 +709,9 @@ add_quadri_to_defect(LocalVector& d, const LocalVector& quadriD) if ( isPrtNode ) { size_t _dof = m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]; - UG_LOG("dof = " << dof << ", _dof = " << _dof << "\n"); - + d.value(fct,_dof) += quadriD.value(fct,dof); - UG_LOG("d = \n" << d << "\n"); - + } } @@ -836,10 +727,12 @@ void ParticleBndCond:: add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) { //////////////////////////////////////////////////////////////////////////////// -// Remove local impulse equations for interface-corners - - ElementModus elemModus = m_spInterfaceHandlerLocal->get_element_modus(elem); // computed via 'compute_element_modus()' during 'update_marker()' - if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling +// (A) Remove local impuls equations for interface-corners +/////////////////////////////////////////////////////////////////////////////// + +// element modus was computed via 'compute_element_modus()' during 'update_interface_data()': + ElementModus elemModus = m_spInterfaceHandlerLocal->get_element_modus(elem); + if ( ! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling { if ( elemModus != INSIDE_DOM ) { @@ -852,7 +745,7 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat for(size_t i = 0; i < m_spInterfaceHandlerLocal->m_vInterfaceID.size(); ++i) { size_t interfaceID = m_spInterfaceHandlerLocal->m_vInterfaceID[i]; - size_t indexToRemove = interfaceID; //m_spInterfaceHandlerLocal->m_vOriginalCornerID[interfaceID]; + size_t indexToRemove = interfaceID; vDoFID.push_back(indexToRemove); } @@ -860,7 +753,11 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat } } - + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// (B) If CUT_BY_2_INTERFACE or StdFVAssembling, no additional interface stresses will be computed +// => map existing entries +//////////////////////////////////////////////////////////////////////////////// if ( elemModus == CUT_BY_2_INTERFACE && !m_spInterfaceHandlerLocal->StdFV_assembling()) { @@ -881,18 +778,16 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat return; } - + //////////////////////////////////////////////////////////////////////////////// +// (C) For CUT_BY_INTERFACE: compute stresses on inner boundary faces 'vBF' +// via 'diffusive_flux_def()' and add the to local defect //////////////////////////////////////////////////////////////////////////////// // initialize data (written during call of 'diffusive_flux_Jac()': LocalIndices ind = u.get_indices(); rotD.resize(ind); rotD = 0.0; - - // ToDo: if ( CUT_BY_2 && m_spInterfaceHandlerLocal->m_vInterfaceID.size() == 2 ) - // => TRIANGLE/5-Eck! => write u( , ) neu!! - // Loop the boundary faces to assemble impulse equations SmartPtr > fluidDensity = m_spMaster->density(); std::vector& vBF = m_spInterfaceHandlerLocal->get_boundary_faces(); @@ -917,7 +812,7 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat // scale with deltaT ( = 1.0 for non-time-dependent) // d *= deltaT; - // ToDo --> NOT necessary, since add_def_A_elem() will be multiplied by 'dt' + // NOT necessary, since add_def_A_elem() will be multiplied by 'dt' // during elem_dis_assemble_util.h ??? if ( fluidDensity->value(0, ip) != fluidDensity->value(1, ip) ) @@ -932,15 +827,8 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat // Continuity equation: if ( 1 ) //! m_spInterfaceHandlerLocal->StdFV_assembling() ) // only remove, if NOT StdFVAssembling d(_P_, bf.node_id()) += VecDot(stdVel, bf.normal()) * importDensity; - // ToDo m_massDefect += VecDot(stdVel, bf.normal()); - } + } -/* if ( elemModus == CUT_BY_INTERFACE ) - if ( m_spInterfaceHandlerLocal->m_vInterfaceID.size() == 2 ) - UG_THROW("vBF.size() = " << vBF.size() << "\n"); -*/ - // copy rotJ_ind/rotJ_rot to m_spInterfaceHandlerLocal data for access from mapper - copy_local_couplings_def(); @@ -962,12 +850,12 @@ add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat return; // B. for outside elements: geo.num_scv() = 0 -// => nothing added during NavierStokesFV1::add_jac_M_elem +// => nothing added during NavierStokesFV1_cutElem::add_jac_M_elem // => nothing will be subtracted here :) /////////////////////////////////////////////////////////////////////////////// -// substract part added by NavierStokesFV1::add_jac_M_elem(): +// substract part added by NavierStokesFV1_cutElem::add_jac_M_elem(): // (instead of setting scv.volume() to zero) //////////////////////////////////////////////////////////////////////////////// @@ -1073,12 +961,12 @@ add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat return; // B. for outside elements: geo.num_scv() = 0 -// => nothing added during NavierStokesFV1::add_jac_M_elem +// => nothing added during NavierStokesFV1_cutElem::add_jac_M_elem // => nothing will be subtracted here :) /////////////////////////////////////////////////////////////////////////////// -// substract part added by NavierStokesFV1::add_jac_M_elem(): +// substract part added by NavierStokesFV1_cutElem::add_jac_M_elem(): // (instead of setting scv.volume() to zero) //////////////////////////////////////////////////////////////////////////////// @@ -1129,6 +1017,7 @@ template void ParticleBndCond:: add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoords[]) { + // no additional rhs, already done by the local-to-global mapper return; @@ -1139,12 +1028,12 @@ add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoor return; // B. for outside elements: geo.num_scv() = 0 -// => nothing added during NavierStokesFV1::add_jac_M_elem +// => nothing added during NavierStokesFV1_cutElem::add_jac_M_elem // => nothing will be subtracted here :) /////////////////////////////////////////////////////////////////////////////// -// substract part added by NavierStokesFV1::add_rgh_elem(): +// substract part added by NavierStokesFV1_cutElem::add_rgh_elem(): // (instead of setting scv.volume() to zero) //////////////////////////////////////////////////////////////////////////////// @@ -1170,66 +1059,6 @@ add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoor d(0, sh) -= scv.volume() * (-9.81); } - - - /* - -REMARK: funktioniert so nicht, da - 'elem->num_vertices()' nicht existiert fuer 'GridObject* elem' :-(... - - => weiterhin 'set_gravity()' in 'local_to_global' verwenden - -// only assembling for single marked element, containing the transVel-DoF - if ( !m_spInterfaceHandlerLocal->m_spParticleHandlerGlobal->m_spTransVelMarker->is_marked(elem) ) - return; - - UG_LOG("------------------------------------------------------------- add_rhs_elem assembling...\n"); - -// A. get location of DoF of translational velocity - size_t transDoF; - for(size_t dof = 0; dof < elem->num_vertices(); ++dof) - if ( m_spInterfaceHandlerLocal->m_spParticleHandlerGlobal->m_spTransVelMarker->is_marked(elem->vertex(dof)) ) - transDoF = dof; - -// B. get corresponding DoFIndex - const size_t fct_gravity = 0; - const LocalIndices& ind = d.get_indices(); - const DoFIndex transInd = DoFIndex(ind.index(fct_gravity,transDoF), ind.comp(fct_gravity,transDoF)); - -// C. compute gravitational force - bool logGravity = true; - - if ( logGravity ) UG_LOG("//////////////////////////////// - log_Gravity - ///////////////////////////////\n"); - if ( logGravity ) UG_LOG("*VORHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); - if ( logGravity ) UG_LOG("*VORHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); - if ( logGravity ) UG_LOG("*VORHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); - if ( logGravity ) UG_LOG("*VORHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); - - const int prtIndex = get_prtIndex(); - const number radius = m_spInterfaceHandlerLocal->m_spParticleHandlerGlobal->get_radius(prtIndex); - number volume; // = Volume(Index,p); // VORSICHT! -> gmg divergiert fuer diese Version: volume = 3.1415*radius*radius; - if ( dim == 2 ) - volume = 3.1415*radius*radius; - if ( dim == 3 ) - volume = 4/3*3.1415*radius*radius*radius; - const number gravitationalMass = volume*1.0; //m_DensityPrt[prtIndex]; //m_EffectiveDensityPrt[p]; - const number gravityForce = -9.81*gravitationalMass; - - if ( logGravity ) UG_LOG ("*radius: " << radius << "\n"); - if ( logGravity ) UG_LOG ("*volume: " << volume << "\n"); - if ( logGravity ) UG_LOG ("*prtIndex: " << prtIndex << "\n"); - - if ( logGravity ) UG_LOG ("*gravForce added: " << gravityForce << "timeFactor: " << timeFactor <<"\n"); - if ( logGravity ) UG_LOG("//////////////////////////////// - log_Gravity - ///////////////////////////////\n"); - if ( logGravity ) UG_LOG("*NACHHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); - if ( logGravity ) UG_LOG("*NACCHHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); - if ( logGravity ) UG_LOG("*NACHHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); - if ( logGravity ) UG_LOG("*NACHHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); - -// D. add gravitational force to rhs - DoFRef(d, transInd) -= gravityForce; - -*/ } @@ -1318,7 +1147,7 @@ register_func() this->set_add_jac_M_elem_fct( id, &T::template add_jac_M_elem); this->set_add_def_A_elem_fct( id, &T::template add_def_A_elem); this->set_add_def_M_elem_fct( id, &T::template add_def_M_elem); - this->set_add_rhs_elem_fct( id, &T::template add_rhs_elem); + this->set_add_rhs_elem_fct( id, &T::template add_rhs_elem); } diff --git a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h index a020ca7..835947a 100644 --- a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h +++ b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h @@ -49,84 +49,143 @@ class ParticleMapper : public IInterfaceMapper /// call base class constructor ParticleMapper(SmartPtr > localHandler) : m_spInterfaceHandlerLocal(localHandler), - m_spParticleHandlerGlobal(m_spInterfaceHandlerLocal->get_cutElementHandler()), - m_gravityConst(0.0), m_bGravity(true), - m_dt(0.0), m_bTimeDep(false), - m_volume(0.0), m_bVolumeCompExact(true), - m_bUsualAss(false), m_meanDiameter(0.0), + m_spCutElementHandler(m_spInterfaceHandlerLocal->get_cutElementHandler()), + m_gravityConst(0.0), + m_bGravity(true), m_bRepulsiveForce(false), m_bGlowRepulsiveForce(false), m_bMinimumCorrectionForce(false), - m_repulsiveDistance(0.0), m_rho(0.0), - m_repulsiveForce(0.0), m_epsilon(0.0), - m_bForceLog(false) - + m_bForceLog(false), + m_rho(0.0), + m_epsilon(0.0), + m_repulsiveForce(0.0), + m_repulsiveDistance(0.0), + m_dt(0.0), + m_bTimeDep(false), + m_meanDiameter(0.0), + m_volume(0.0), + m_bVolumeCompExact(true), + m_bUsualAss(false) { // init boolian arrays for all registered particles size_t numPrt = num_particles(); m_bFlagGravity.resize(numPrt, false); m_bFlagInertial.resize(numPrt, false); -// particleValues.data.resize(numPrt); }; /// destructor - ~ParticleMapper() {}; + virtual ~ParticleMapper() {}; /////////////////////////////////////////////////////////////////////////////// /// - /// base class methods and helper methods called by them + /// base class methods not needed for this class /// /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - /// A. local vector to global - - /// send local entries to global vector - virtual void add_local_vec_to_global(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd); - virtual void add_local_vec_to_global_interface(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd); - virtual void add_local_vec_to_global_interface_for2(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd); + void adjust_mat_global(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd){}; - void adjust_mat_global(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd){}; + /////////////////////////////////////////////////////////////////////////////// + /// + /// A. send local entries to global vector + /// + /////////////////////////////////////////////////////////////////////////////// - void add_mass_part_def(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); - void add_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); - void set_gravitational_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); - void add_repulsive_force_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); - void add_glowinski_repulsive_force_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); - void add_minimum_correction_force_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); + /// base method + virtual void add_local_vec_to_global(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd); + + /// methods called by base method for cut element case + virtual void add_local_vec_to_global_interface(vector_type& vec, const LocalVector& lvec, + ConstSmartPtr dd); + + /// methods called by base method for the case, that TWO elements are cut by interface + /// --> tag: CUT_BY_2_INTERFACE + /// REMARK: not finally tested!! + virtual void add_local_vec_to_global_interface_for2(vector_type& vec, const LocalVector& lvec, + ConstSmartPtr dd); + + /// central method to write/map the entries for fluid-particle coupling + virtual void add_local_vec_to_global_FT(vector_type& vec, const LocalVector& lvec, std::vector transInd, + std::vector rotInd); + + /// sends local entries to particle DoFs in case of two particles, cutting an element + /// --> tag: CUT_BY_2_INTERFACE + /// REMARK: not finally tested!! + virtual void add_local_vec_to_global_FT_for2_StdFV(vector_type& vec, const LocalVector& lvec, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2); + virtual void add_local_vec_to_global_FT_for2(vector_type& vec, const LocalVector& lvec, + std::vector transInd1, std::vector rotInd1, + std::vector transInd2, std::vector rotInd2); + + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// B. assemble components of the rhs for the particle + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // for time dependent case + void add_mass_part_def(vector_type& vec, std::vector transInd, + std::vector rotInd, const int levIndex, const int prtIndex); + + // called during 'add_local_vec_to_global_interface()': calls according components for assemgling the rhs + // (see methods below) + void add_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, + const int levIndex, const int prtIndex); + + // additional methods called by 'add_rhs()': + void set_gravitational_rhs(vector_type& vec, std::vector transInd, + std::vector rotInd, const int levIndex, const int prtIndex); + void add_repulsive_force_rhs(vector_type& vec, std::vector transInd, + std::vector rotInd, const int levIndex, const int prtIndex); + void add_glowinski_repulsive_force_rhs(vector_type& vec, std::vector transInd, + std::vector rotInd, const int levIndex, const int prtIndex); + void add_minimum_correction_force_rhs(vector_type& vec, std::vector transInd, + std::vector rotInd, const int levIndex, const int prtIndex); - void map_all_local_vec_to_transDoF(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd); - virtual void add_local_vec_to_global_FT(vector_type& vec, const LocalVector& lvec, std::vector transInd, std::vector rotInd); - virtual void add_local_vec_to_global_FT_for2_StdFV(vector_type& vec, const LocalVector& lvec, - std::vector transInd1, std::vector rotInd1, - std::vector transInd2, std::vector rotInd2); - virtual void add_local_vec_to_global_FT_for2(vector_type& vec, const LocalVector& lvec, - std::vector transInd1, std::vector rotInd1, - std::vector transInd2, std::vector rotInd2); + + /////////////////////////////////////////////////////////////////////////////// /// helper function for 'add_local_vec_to_global_FT_for2()': + /// --> tag: CUT_BY_2_INTERFACE + // REMARK: not finally tested! + + /// special mapping of local DoFs due to element, cut by two particles size_t map_for2(size_t dof); - - /// called during 'add_local_vec_to_global_FT_for2()': - void assemble_fluid_nodes(vector_type& vec, const LocalVector& lvec); - + /// called during 'add_local_vec_to_global_FT_for2()': void assemble_QuadriCorners(vector_type& vec, const LocalVector& lvec, std::vector transInd1, std::vector rotInd1, std::vector transInd2, std::vector rotInd2); + /////////////////////////////////////////////////////////////////////////////// - /// B. local matrix to global + /// + /// C. local matrix to global + /// + /////////////////////////////////////////////////////////////////////////////// - /// send local entries to global rhs + + /// base method virtual void add_local_mat_to_global(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd); - virtual void add_local_mat_to_global_interface(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd); - virtual void add_local_mat_to_global_interface_for2(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd); - - void add_mass_part_jac(matrix_type& mat, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex); - void map_all_local_mat_to_transDoF(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd); + + /// methods called by base method for cut element case + virtual void add_local_mat_to_global_interface(matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd); + + /// methods called by base method for the case, that TWO elements are cut by interface + /// --> tag: CUT_BY_2_INTERFACE + /// REMARK: not finally tested!! + virtual void add_local_mat_to_global_interface_for2(matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd); + + /// central method to write/map the entries for fluid-particle coupling --> tag: CUT_BY_INTERFACE virtual void add_local_mat_to_global_FT(matrix_type& mat, const LocalMatrix& lmat, - std::vector transInd, std::vector rotInd); + std::vector transInd, std::vector rotInd); + + /// sends local entries to particle DoFs in case of two particles, cutting an element + /// --> tag: CUT_BY_2_INTERFACE + /// REMARK: not finally tested!! virtual void add_local_mat_to_global_FT_for2_StdFV(matrix_type& mat, const LocalMatrix& lmat, std::vector transInd1, std::vector rotInd1, std::vector transInd2, std::vector rotInd2); @@ -134,9 +193,16 @@ class ParticleMapper : public IInterfaceMapper std::vector transInd1, std::vector rotInd1, std::vector transInd2, std::vector rotInd2); - /// instead of calling base class method 'set_identity_mat()': - /// -> IFF element does NOT include transInd/rotInd-node! - void set_identity_mat_constraint(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd); + + // for time dependent case + void add_mass_part_jac(matrix_type& mat, std::vector transInd, + std::vector rotInd, const int levIndex, const int prtIndex); + + /// sets dirichlet rows for DoFs lying outside the fluid + /// -> IFF element does NOT include transInd/rotInd-node! (which also lie outside fluid, + /// i.e. inside the particle domain + void set_identity_mat_constraint(matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd); /////////////////////////////////////////////////////////////////////////////// /// REMARK: @@ -145,79 +211,125 @@ class ParticleMapper : public IInterfaceMapper /// ---> m_spAssTuner->modify_LocalData(pModifyMemory, vSol, dd); /////////////////////////////////////////////////////////////////////////////// - /// modifies local solution vector for adapted defect computation - virtual void modify_LocalData(LocalMatrix& locJ, LocalVector& locU, ConstSmartPtr dd); - virtual void modify_LocalData(LocalVectorTimeSeries& uT, LocalMatrix& locJ, LocalVector& locU, ConstSmartPtr dd); - - virtual void modify_LocalData(LocalVector& locD, LocalVector& tmpLocD, LocalVector& locU, ConstSmartPtr dd); - virtual void modify_LocalData(LocalVectorTimeSeries& uT, LocalVector& locD, LocalVector& tmpLocD, LocalVector& locU, - ConstSmartPtr dd, size_t t); + /// resizes local solution vector for the assemlby on cut elements, which + /// potentially have more nodes than the original element + virtual void modify_LocalData(LocalMatrix& locJ, LocalVector& locU, + ConstSmartPtr dd); + virtual void modify_LocalData(LocalVectorTimeSeries& uT, LocalMatrix& locJ, + LocalVector& locU, ConstSmartPtr dd); + + /// (1) resizes local solution vector for the assemlby on cut elements, which + /// potentially have more nodes than the original element + /// (2) writes the particle velocities in the designated, local particle indices + virtual void modify_LocalData(LocalVector& locD, LocalVector& tmpLocD, LocalVector& locU, + ConstSmartPtr dd); + virtual void modify_LocalData(LocalVectorTimeSeries& uT, LocalVector& locD, LocalVector& tmpLocD, + LocalVector& locU, ConstSmartPtr dd, size_t t); /// method called during 'modify_LocalData()' to set local sol for CUT_BY_2_INTERFACE void set_QuadriSol(LocalVector& locU, LocalVector& locD); - /// called during 'modify_LocalData(locU)' + /// called during 'modify_LocalData(locU)': + /// copies old local vector to the new local algebra due to cut element void map_local_data(LocalVector& d); - /// called during modify_LocalData() for resizing: + /// called during modify_LocalData() for resizing local data on cut elements: void resize_local_indices(LocalVector& locU) - { m_spInterfaceHandlerLocal->resize_local_indices(locU); } + { m_spInterfaceHandlerLocal->resize_local_indices(locU); } void resize_local_indices(LocalVector& locU, size_t numCo) - { m_spInterfaceHandlerLocal->resize_local_indices(locU, numCo); } + { m_spInterfaceHandlerLocal->resize_local_indices(locU, numCo); } - /// calls m_spParticleHandlerGlobal->set_extraSolTrans/Rot - /// called during 'modify_GlobalSol' - void set_extraSol(vector_type& vec, std::vector transInd, std::vector rotInd, const int timeIndex, const int prtIndex); + // writes/copies the linear and angular velocity of the particle to data storage + // in 'ParticleProvider:m_vvLinearVelocity' (called during 'modify_GlobalSol') + void set_extraSol(vector_type& vec, std::vector transInd, std::vector rotInd, + const int timeIndex, const int prtIndex); /////////////////////////////////////////////////////////////////////////////// /// REMARK: /// During DomainDiscretization::assemble_jacobian: /// calling /// ---> m_spAssTuner->modify_GlobalSol(pModifyMemory, vSol, dd); - /// instead of calling - /// ----> m_vConstraint[i]->modify_solution(pModifyMemory, vSol, dd); /////////////////////////////////////////////////////////////////////////////// - /// modifies local solution vector for adapted defect computation + /// the method 'modify_GlobalSol()' does not 'modify' the solution, but: the + /// computed solution at the trans und rot DoFs gets written/stored into data of + /// class 'ParticleProvider::m_vvLinearVelocity/m_vvAngularVelocity', + /// since they will be overwritten during the local computation of defect + /// (for each call of domainDisc, i.e. newton step) + virtual void modify_GlobalSol(vector_type& uMod, const vector_type& u, ConstSmartPtr dd); virtual void modify_GlobalSol(SmartPtr > vSolMod, ConstSmartPtr > vSol, ConstSmartPtr dd); /////////////////////////////////////////////////////////////////////////////// - /// Further helper methods: + /// setter methods: /////////////////////////////////////////////////////////////////////////////// - int getPrtIndex(size_t dof){ return m_spInterfaceHandlerLocal->getPrtIndex(dof);} - int getMappingModus(size_t fct1, size_t dof1, size_t fct2, size_t dof2); - int getMappingModus_for2(size_t fct1, size_t dof1, size_t fct2, size_t dof2); - int get_prtIndex() { return this->m_spInterfaceHandlerLocal->get_prtIndex(); } - size_t num_particles() const { return m_spParticleHandlerGlobal->num_particles();} - bool UsualAss() { return m_bUsualAss; } - - void set_bUsualAss(bool UsualAss) { m_bUsualAss = UsualAss; } - - void set_gravity(bool gravity, number gravityConst) { m_bGravity = gravity; m_gravityConst = gravityConst;} - void set_repulsive_force(bool repulsive, number forceValue) {m_bRepulsiveForce = repulsive; m_repulsiveForce = forceValue;} - void set_glowinski_repulsive_force(bool repulsive, number rho, number epsilon) {m_bGlowRepulsiveForce = repulsive; m_rho = rho; m_epsilon = epsilon;} - void set_minimum_correction_force(bool repulsive, number equiDist) {m_bMinimumCorrectionForce = repulsive; m_repulsiveDistance = equiDist;} + void set_gravity(bool gravity, number gravityConst) + { m_bGravity = gravity; m_gravityConst = gravityConst;} + void set_repulsive_force(bool repulsive, number forceValue) + {m_bRepulsiveForce = repulsive; m_repulsiveForce = forceValue;} + void set_glowinski_repulsive_force(bool repulsive, number rho, number epsilon) + {m_bGlowRepulsiveForce = repulsive; m_rho = rho; m_epsilon = epsilon;} + void set_minimum_correction_force(bool repulsive, number equiDist) + {m_bMinimumCorrectionForce = repulsive; m_repulsiveDistance = equiDist;} + void set_bUsualAss(bool UsualAss) { m_bUsualAss = UsualAss; } void set_volume_comp_mode(bool bVolumeCompMode) { m_bVolumeCompExact = bVolumeCompMode;} + void set_time_step(number dt) { m_dt = dt; set_time_dependent(true);} + void set_time_dependent(bool bTimeDep) { m_bTimeDep = bTimeDep; } + void set_element_diameter(double diameter) { m_meanDiameter = diameter;} + + // flag for output + void set_forceLog(bool val) {m_bForceLog = val;} - bool gravitation_force() { return m_bGravity; } - - void set_time_step(number dt) { m_dt = dt; set_time_dependent(true);} - - void set_time_dependent(bool bTimeDep) { m_bTimeDep = bTimeDep; } - bool is_time_dependent() { return m_bTimeDep;} - - void set_element_diameter(double diameter){m_meanDiameter = diameter;UG_LOG("Mean element diameter is " << m_meanDiameter);} - + + /////////////////////////////////////////////////////////////////////////////// + /// getter methods: + /////////////////////////////////////////////////////////////////////////////// + + // gets the current index of the particle, which cuts the current element; + // stored in 'InterfaceHandlerLocalParticle' + int get_prtIndex() { return this->m_spInterfaceHandlerLocal->get_prtIndex(); } + + // IFF two particles cut an element: gets the index of the particle, to which + // the node with local index 'dof' belongs + int getPrtIndex(size_t dof) { return m_spInterfaceHandlerLocal->getPrtIndex(dof);} + + size_t num_particles() const { return m_spCutElementHandler->num_particles();} + bool UsualAss() { return m_bUsualAss; } + bool is_time_dependent() { return m_bTimeDep;} + bool gravitation_force() { return m_bGravity; } + number get_time_step() - { if ( !is_time_dependent() ) UG_THROW("Call for time step, BUT: not timedependent computation!\n"); - return m_dt; } + { if ( !is_time_dependent() ) + UG_THROW("Call for time step, BUT: not timedependent computation!\n"); + return m_dt; } + + /// checks if grid data is updated and returns the 'levIndex' of the 'gridLevel' + /// via access to 'CutElementHandlerBase::m_Map' + int get_Index(const GridLevel& gridLevel, ConstSmartPtr dd) + { return m_spCutElementHandler->get_Index(gridLevel, dd); } + + ///////////////////////////////////////////////////////////////////////////////////// + // the mapping modus inherits the coupling categorie + // --> pair combinations (from,to) of: velDoF in fluid, velDoF in particle, + // pressureDoF in fluid, pressureDof on particle boundary + // + // => for the case 'pressureDof on particle boundary': is treated as usual DoF + // => ONLY for the case 'velDoF in particle' mapping to the global index needs to be + // changed (for the row or column) and in case of rotational DoF also different + // values (multiplied by rotationMat) need to be choosen + ///////////////////////////////////////////////////////////////////////////////////// + + int getMappingModus(size_t fct1, size_t dof1, size_t fct2, size_t dof2); + int getMappingModus_for2(size_t fct1, size_t dof1, size_t fct2, size_t dof2); + - // access methods for '..._FT()': + // access to 'LocalMatrix' data within 'ParticleBndCond' class + // (used during 'add_local_mat_to_global_FT()' in case the boundary + // conditions were computed by the class 'ParticleBndCond') number get_rotJ_ind(size_t fct1, size_t dof1, size_t fct2, size_t dof2) { return m_spInterfaceHandlerLocal->get_rotJ_ind(fct1, dof1, fct2, dof2); } number get_rotJ_rot(size_t fct1, size_t dof1, size_t fct2, size_t dof2) @@ -226,69 +338,77 @@ class ParticleMapper : public IInterfaceMapper number get_rotD(size_t fct, size_t dof) { return m_spInterfaceHandlerLocal->get_rotD(fct, dof); } - int get_Index(const GridLevel& gridLevel, ConstSmartPtr dd) - { return m_spParticleHandlerGlobal->get_Index(gridLevel, dd); } - - void reset_volume(){m_volume = 0.0;} + + /////////////////////////////////////////////////////////////////////////////// + /// Forwarding computational methods to the interface provider: + /////////////////////////////////////////////////////////////////////////////// + // analytical computation of the volume of a dics/sphere number Volume(int levIndex, size_t prtIndex) - { return m_spParticleHandlerGlobal->Volume(levIndex, prtIndex); } + { return m_spCutElementHandler->Volume(levIndex, prtIndex); } number Mass(const int levIndex, const int prtIndex) - { return m_spParticleHandlerGlobal->Mass(levIndex, prtIndex, m_spInterfaceHandlerLocal->get_density_fluid()); } + { return m_spCutElementHandler->Mass(levIndex, prtIndex, m_spInterfaceHandlerLocal->get_density_fluid()); } number Mass(const int levIndex, const int prtIndex, const number volume) - { return m_spParticleHandlerGlobal->Mass(levIndex, prtIndex, volume, m_spInterfaceHandlerLocal->get_density_fluid()); } + { return m_spCutElementHandler->Mass(levIndex, prtIndex, volume, m_spInterfaceHandlerLocal->get_density_fluid()); } number MomOfInertia(const int levIndex, const int prtIndex) - { return m_spParticleHandlerGlobal->MomOfInertia(levIndex, prtIndex, m_spInterfaceHandlerLocal->get_density_fluid()); } + { return m_spCutElementHandler->MomOfInertia(levIndex, prtIndex, m_spInterfaceHandlerLocal->get_density_fluid()); } number MomOfInertia(const int levIndex, const int prtIndex, const number volume) - { return m_spParticleHandlerGlobal->MomOfInertia(levIndex, prtIndex, volume, m_spInterfaceHandlerLocal->get_density_fluid()); } + { return m_spCutElementHandler->MomOfInertia(levIndex, prtIndex, volume, m_spInterfaceHandlerLocal->get_density_fluid()); } - number compute_volume(int levIndex, size_t prtIndex); - - void set_forceLog(bool val) { - m_bForceLog = val; - } + // if m_bVolumeCompExact = false: the volume will computed based on the volume of the parts + // covered by in the particle, instead of using the analytical formular for a disc/sphere + number compute_volume(int levIndex, size_t prtIndex); + void reset_volume(){m_volume = 0.0;} + + /////////////////////////////////////////////////////////////////////////////// + /// class member + /////////////////////////////////////////////////////////////////////////////// private: // member from base class SmartPtr > m_spInterfaceHandlerLocal; // new member - SmartPtr > m_spParticleHandlerGlobal; + SmartPtr > m_spCutElementHandler; // gravityConst for call during 'set_gravitational_rhs()' number m_gravityConst; // boolian to add gravity force to global defect during 'add_local_vec_to_global_interface()' - bool m_bGravity; // default = false; + bool m_bGravity; // default = false; + + /// handles the call of'set_gravity()' exactly ONCE during 'modify_LocalData()' + std::vector m_bFlagGravity; // default = false + + /// handles the call of'set_gravity()' exactly ONCE during 'modify_LocalData()' + std::vector m_bFlagInertial; // default = false + // boolian to add repulsive force in 'add_rhs()' bool m_bRepulsiveForce; bool m_bGlowRepulsiveForce; bool m_bMinimumCorrectionForce; + bool m_bForceLog; number m_rho; number m_epsilon; number m_repulsiveForce; number m_repulsiveDistance; // used within 'set_gravitational_rhs()' for computation of rhs - number m_dt; // default = 0.0; + number m_dt; // default = 0.0; bool m_bTimeDep; // used within 'add_repulsive_force' for computation of rhs double m_meanDiameter; - - /// handles the call of'set_gravity()' exactly ONCE during 'modify_LocalData()' - std::vector m_bFlagGravity; // default = false - - /// handles the call of'set_gravity()' exactly ONCE during 'modify_LocalData()' - std::vector m_bFlagInertial; // default = false - + // used for the iterative computation of the volume, if not computet analytically number m_volume; - bool m_bVolumeCompExact; - bool m_bUsualAss; // default = false; + bool m_bVolumeCompExact; // default = true; if false, the volume will computed based + // on the volume of the parts covered by in the particle, + // instead of using the analytical formular for a disc/sphere + + bool m_bUsualAss; // default = false; - bool m_bForceLog; }; @@ -298,7 +418,6 @@ class ParticleMapper : public IInterfaceMapper #include "loc_to_glob_mapper_particle_impl.h" -#include "loc_to_glob_mapper_particle_tools.h" diff --git a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h index 463b590..fc5ebc5 100644 --- a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h +++ b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h @@ -33,8 +33,7 @@ compute_volume(int levIndex, size_t prtIndex) if (dim == 2 && m_spInterfaceHandlerLocal->m_vBF.size() != 2 && m_spInterfaceHandlerLocal->m_vBF.size() != 0) { - UG_LOG( - "m_spInterfaceHandlerLocal->m_vBF.size() = " << m_spInterfaceHandlerLocal->m_vBF.size() << "\n"); + UG_LOG("m_spInterfaceHandlerLocal->m_vBF.size() = " << m_spInterfaceHandlerLocal->m_vBF.size() << "\n"); UG_THROW("oha, this->m_vBF.size() != 2 && != 0:\n"); } @@ -46,7 +45,7 @@ compute_volume(int levIndex, size_t prtIndex) MathVector midPoint(0.0); std::vector > vCorners; - const MathVector center = m_spParticleHandlerGlobal->get_center( + const MathVector center = m_spCutElementHandler->get_center( prtIndex); std::vector < interfaceBF > &vBF = m_spInterfaceHandlerLocal->get_boundary_faces(); @@ -101,47 +100,53 @@ compute_volume(int levIndex, size_t prtIndex) m_volume += volume; if (output) { - UG_LOG( - "nachher (levIndex = " << levIndex << "): m_volume = " << m_volume << "\n"); + UG_LOG("nachher (levIndex = " << levIndex << "): m_volume = " << m_volume << "\n"); UG_LOG("ref Volume = " << Volume(levIndex,prtIndex) << "\n"); } + return volume; } template int ParticleMapper:: -getMappingModus(size_t fct1, size_t dof1, size_t fct2, size_t dof2) { +getMappingModus(size_t fct1, size_t dof1, size_t fct2, size_t dof2) +{ +// if 'dof1' lies on interface, it is a particle from-DoF, i.e. momEq for particle +// if 'dof2' lies on interface, it is a particle to-DoF bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(dof1); bool isPrtConn = m_spInterfaceHandlerLocal->remapped_fromInterface(dof2); -// fluid->fluid: +// fluidDoF -> fluidDoF: if (!isPrtNode && !isPrtConn) return 0; -// fluid->particle: +// fluidDoF -> prtDoF: if (!isPrtNode && isPrtConn) { + // fluidDoF -> interfacePressure: if (fct2 == dim) return 0; // = connection to pressure on interface! else return 1; } -// particle->fluid: +// prtDoF -> fluidDoF: if (isPrtNode && !isPrtConn) { + // prtPressure -> fluidDoF if (fct1 == dim) return 0; // = ContEq on interface! else return 2; } -// particle->particle: +// prtDoF -> prtDoF: if (isPrtNode && isPrtConn) { + // interfacePressure -> interfacePressure if (fct1 == dim && fct2 == dim) return 0; else if (fct1 == dim) - return 1; // prt-vel in ContEq => fluid->particle + return 1; // prtDoF in ContEq => = fluidDoF -> prtDoF else if (fct2 == dim) { if (m_spInterfaceHandlerLocal->elementModus() != OUTSIDE_DOM) - return 2; // pressure in prt-ImpEq => particle->fluid + return 2; // pressure in prt-ImpEq => prtDoF -> fluidDoF else return 4; } else @@ -153,9 +158,9 @@ getMappingModus(size_t fct1, size_t dof1, size_t fct2, size_t dof2) { } template -int ParticleMapper::getMappingModus_for2(size_t fct1, - size_t dof1, size_t fct2, size_t dof2) { - +int ParticleMapper:: +getMappingModus_for2(size_t fct1, size_t dof1, size_t fct2, size_t dof2) +{ // fluid->... if (fct1 == _P_ || dof1 == 4) { // fluid->fluid: @@ -180,258 +185,194 @@ int ParticleMapper::getMappingModus_for2(size_t fct1, } template -void ParticleMapper::set_extraSol(vector_type& vec, - std::vector transInd, std::vector rotInd, - const int timeIndex, const int prtIndex) { - for (int d = 0; d < dim; ++d) { - // A. if the linear velocity is given by the user, is needs NOT to be set - if (!m_spParticleHandlerGlobal->get_DoF_modus_linear(prtIndex)) - m_spParticleHandlerGlobal->set_extraSolTrans( +void ParticleMapper:: +set_extraSol(vector_type& vec, std::vector transInd, std::vector rotInd, + const int timeIndex, const int prtIndex) +{ + for (int d = 0; d < dim; ++d) + { + // A. write linear velocity to data storage in 'ParticleProvider:m_vvLinearVelocity' + // --> if the linear velocity is given by the user, it does NOT need to be set + if (!m_spCutElementHandler->get_DoF_modus_linear(prtIndex)) + m_spCutElementHandler->set_extraSolTrans( DoFRef(vec, transInd[d]), prtIndex, timeIndex, d); - // B. if the angular velocity is given by the user, is needs NOT to be set - if (!m_spParticleHandlerGlobal->get_DoF_modus_anguar(prtIndex)) - m_spParticleHandlerGlobal->set_extraSolRot(DoFRef(vec, rotInd[d]), - prtIndex, timeIndex, d); + + // B. write angular velocity to data storage in 'ParticleProvider:m_vvAngularVelocity' + // --> if the angular velocity is given by the user, it does NOT need to be set + if (!m_spCutElementHandler->get_DoF_modus_anguar(prtIndex)) + m_spCutElementHandler->set_extraSolRot( + DoFRef(vec, rotInd[d]), prtIndex, timeIndex, d); } } template -void ParticleMapper::modify_GlobalSol( +void ParticleMapper:: +modify_GlobalSol( SmartPtr > vSolMod, ConstSmartPtr > vSol, - ConstSmartPtr dd) { - UG_LOG("begin modify_Glob\n"); - + ConstSmartPtr dd) +{ + bool output = false; + // some checks if (vSol->size() != 2) - UG_THROW( - "ParticleMapper::modify_GlobalSol: method needs exactly two time points."); + UG_THROW("ParticleMapper::modify_GlobalSol: method needs exactly two time points."); if (!is_time_dependent()) set_time_dependent(true); const int levIndex = get_Index(dd->grid_level(), dd); - for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + for (size_t p = 0; p < m_spCutElementHandler->num_particles(); ++p) { m_bFlagInertial[p] = true; if (gravitation_force()) { - UG_LOG("modify_GlobalSol: set m_bFlagGravity from 'false' to 'true'\n"); m_bFlagGravity[p] = true; } - // linear AND angular velocity are given by the user: - if (m_spParticleHandlerGlobal->get_DoF_modus_linear(p) - && m_spParticleHandlerGlobal->get_DoF_modus_angular(p)) + // iFF linear AND angular velocity are given by the user: no storing necessary + if (m_spCutElementHandler->get_DoF_modus_linear(p) + && m_spCutElementHandler->get_DoF_modus_angular(p)) continue; - std::vector ElemList = - m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; - #ifdef UG_PARALLEL - UG_LOG( - "1 NavierStokes::modify_GlobalSol: ElemList.size(): " << ElemList.size() << "\n"); + // use size of member 'CutElementHandler_FlatTop::m_vvvElemListCut' in order to + // indicate, whether a particle lies on a processor or not + std::vector ElemList = + m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; + UG_LOG("1 NavierStokes::modify_GlobalSol: ElemList.size(): " << ElemList.size() << "\n"); if (ElemList.size() == 0) { - UG_LOG( - "2 NavierStokes::modify_GlobalSol: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + UG_LOG("2 NavierStokes::modify_GlobalSol: ElemList.size(): " + << ElemList.size() << " => skip assembling! \n"); continue; } #endif - // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) - std::vector < DoFIndex > transInd = - m_spParticleHandlerGlobal->get_transInd(levIndex, p); - std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd( - levIndex, p); -#ifdef UG_DEBUG + // REMARK: 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) + std::vector < DoFIndex > transInd = m_spCutElementHandler->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spCutElementHandler->get_rotInd(levIndex, p); + + if ( output ){ UG_LOG("in modify_GlobalSol: transInd: " << transInd[0] << "\n"); UG_LOG("in modify_GlobalSol: rotInd: " << rotInd[0] << "\n"); - UG_LOG( - "VORHER: modify_GlobalSol transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); - UG_LOG( - "VORHER: modify_GlobalSol transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); - UG_LOG( - "VORHER: modify_GlobalSol rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); - UG_LOG( - "VORHER: modify_GlobalSol rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); -#endif - // loop all time points and assemble them + UG_LOG("VORHER: modify_GlobalSol transSol(0) = " << m_spCutElementHandler->get_transSol(p,0) << "\n"); + UG_LOG("VORHER: modify_GlobalSol transSol(1) = " << m_spCutElementHandler->get_transSol(p, 1) << "\n"); + UG_LOG("VORHER: modify_GlobalSol rotSol(0) = " << m_spCutElementHandler->get_rotSol(p,0) << "\n"); + UG_LOG("VORHER: modify_GlobalSol rot1Sol(1) = " << m_spCutElementHandler->get_rotSol(p, 1) << "\n"); + } + + // loop all time points and assemble them for (int i = vSol->size() - 1; i >= 0; --i) { number solution; -#ifdef UG_DEBUG - UG_LOG("in modify_GlobalSol: transInd: " << transInd[0] << "\n"); - - - //set_extraSol(*vSol->solution(i), transInd, rotInd, i, p); - - /* MathVector solution = m_spParticleHandlerGlobal->get_transSol(p,i); - m_spParticleHandlerGlobal->set_extraSolTrans(solution, p, i); - UG_LOG("solution(" << i << ") = " << solution << "\n"); - - solution = m_spParticleHandlerGlobal->get_transSol(p,i); - m_spParticleHandlerGlobal->set_extraSolRot(solution, p, i); - - UG_LOG("solution(" << i << ") = " << solution << "\n"); - */ - for (int d = 0; d < dim; ++d) { - UG_LOG("d = " << d << "\n"); - - // A. if the linear velocity is given by the user, it needs NOT to be set - if (!m_spParticleHandlerGlobal->get_DoF_modus_linear(p)) { - UG_LOG("1: solution = " << solution << "\n"); - UG_LOG( - "in modify_GlobalSol: transInd[d]: " << transInd[d] << "\n"); - - solution = DoFRef(*vSol->solution(i), transInd[d]); - UG_LOG("2: solution = " << solution << "\n"); - - m_spParticleHandlerGlobal->set_extraSolTrans(solution, p, i, - d); - UG_LOG("transSol(" << i << " = " << solution << "\n"); - } - - // B. if the angular velocity is given by the user, it needs NOT to be set - if (!m_spParticleHandlerGlobal->get_DoF_modus_angular(p)) { - UG_LOG("3: solution = " << solution << "\n"); - - solution = DoFRef(*vSol->solution(i), rotInd[d]); - UG_LOG("4: solution = " << solution << "\n"); - - m_spParticleHandlerGlobal->set_extraSolRot(solution, p, i, - d); - UG_LOG("rotSol(" << i << " = " << solution << "\n"); - } - - } -#else - for (int d = 0; d < dim; ++d) { - if (!m_spParticleHandlerGlobal->get_DoF_modus_linear(p)) { + for (int d = 0; d < dim; ++d) + { + // A. if the linear velocity is given by the user, it needs NOT to be set + if (!m_spCutElementHandler->get_DoF_modus_linear(p)) + { solution = DoFRef(*vSol->solution(i), transInd[d]); - m_spParticleHandlerGlobal->set_extraSolTrans(solution, p, i, d); + m_spCutElementHandler->set_extraSolTrans(solution, p, i, d); } - // B. if the angular velocity is given by the user, is needs NOT to be set - if (!m_spParticleHandlerGlobal->get_DoF_modus_angular(p)) { + // B. if the angular velocity is given by the user, is needs NOT to be set + if (!m_spCutElementHandler->get_DoF_modus_angular(p)) + { solution = DoFRef(*vSol->solution(i), rotInd[d]); - m_spParticleHandlerGlobal->set_extraSolRot(solution, p, i, d); + m_spCutElementHandler->set_extraSolRot(solution, p, i, d); } } -#endif + } // end time series loop -#ifdef UG_DEBUG - UG_LOG( - "NACHHER: modify_GlobalSol transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); - UG_LOG( - "NACHHER: modify_GlobalSol transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); - UG_LOG( - "NACHHER: modify_GlobalSol rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); - UG_LOG( - "NACHHER: modify_GlobalSol rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); -#endif - } // end particle loop - - UG_LOG("end modify_Glob\n"); + + if ( output ){ + UG_LOG("NACHHER: modify_GlobalSol transSol(0) = " << m_spCutElementHandler->get_transSol(p,0) << "\n"); + UG_LOG("NACHHER: modify_GlobalSol transSol(1) = " << m_spCutElementHandler->get_transSol(p, 1) << "\n"); + UG_LOG("NACHHER: modify_GlobalSol rotSol(0) = " << m_spCutElementHandler->get_rotSol(p,0) << "\n"); + UG_LOG("NACHHER: modify_GlobalSol rot1Sol(1) = " << m_spCutElementHandler->get_rotSol(p, 1) << "\n"); + } + } // end particle loop } template -void ParticleMapper::modify_GlobalSol(vector_type& uMod, - const vector_type& u, ConstSmartPtr dd) { +void ParticleMapper:: +modify_GlobalSol(vector_type& uMod, + const vector_type& u, ConstSmartPtr dd) +{ + bool output = false; + if (is_time_dependent()) set_time_dependent(false); const int levIndex = get_Index(dd->grid_level(), dd); - for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + for (size_t p = 0; p < m_spCutElementHandler->num_particles(); ++p) + { if (gravitation_force()) { - UG_LOG( - "modify_GlobalSol: set m_bFlagGravity from 'false' to 'true'\n"); m_bFlagGravity[p] = true; } - // linear AND angular velocity are given by the user: - if (m_spParticleHandlerGlobal->get_DoF_modus_linear(p) - && m_spParticleHandlerGlobal->get_DoF_modus_angular(p)) { -#ifdef UG_DEBUG - UG_LOG( - "continue... in modify_GlobalSol for transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); - UG_LOG( - "continue... in modify_GlobalSol for transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); - UG_LOG( - "continue... in modify_GlobalSol for rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); - UG_LOG( - "continue... in modify_GlobalSol for rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); -#endif + // IFF linear AND angular velocity are given by the user: no need for storing + if (m_spCutElementHandler->get_DoF_modus_linear(p) + && m_spCutElementHandler->get_DoF_modus_angular(p)) { continue; } - std::vector ElemList = - m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; #ifdef UG_PARALLEL - UG_LOG( - "1 NavierStokes::modify_GlobalSol: ElemList.size(): " << ElemList.size() << "\n"); + // use size of member 'CutElementHandler_FlatTop::m_vvvElemListCut' in order to + // indicate, whether a particle lies on a processor or not + std::vector ElemList = + m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; + UG_LOG("1 NavierStokes::modify_GlobalSol: ElemList.size(): " << ElemList.size() << "\n"); if (ElemList.size() == 0) { - UG_LOG( - "2 NavierStokes::modify_GlobalSol: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + UG_LOG("2 NavierStokes::modify_GlobalSol: ElemList.size(): " + << ElemList.size() << " => skip assembling! \n"); continue; } #endif - // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) - std::vector < DoFIndex > transInd = - m_spParticleHandlerGlobal->get_transInd(levIndex, p); - std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd( - levIndex, p); -#ifdef UG_DEBUG - UG_LOG( - "VORHER: modify_GlobalSol transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); - UG_LOG( - "VORHER: modify_GlobalSol transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); - UG_LOG( - "VORHER: modify_GlobalSol rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); - UG_LOG( - "VORHER: modify_GlobalSol rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); -#endif - // set_extraSol(u, transInd, rotInd, 0, p); + // REMARK: 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) + std::vector < DoFIndex > transInd = m_spCutElementHandler->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spCutElementHandler->get_rotInd(levIndex, p); + + if (output ){ + UG_LOG("VORHER: modify_GlobalSol transSol(0) = " << m_spCutElementHandler->get_transSol(p,0) << "\n"); + UG_LOG("VORHER: modify_GlobalSol transSol(1) = " << m_spCutElementHandler->get_transSol(p, 1) << "\n"); + UG_LOG("VORHER: modify_GlobalSol rotSol(0) = " << m_spCutElementHandler->get_rotSol(p,0) << "\n"); + UG_LOG("VORHER: modify_GlobalSol rot1Sol(1) = " << m_spCutElementHandler->get_rotSol(p, 1) << "\n"); + } + // set_extraSol(u, transInd, rotInd, 0, p); number solution; - for (int d = 0; d < dim; ++d) { -#ifdef UG_DEBUG - UG_LOG("transInd[" << d << "] = " << transInd[d] << "\n"); - UG_LOG("rotInd[" << d << "] = " << rotInd[d] << "\n"); -#endif - // A. if the linear velocity is given by the user, is needs NOT to be set - if (!m_spParticleHandlerGlobal->get_DoF_modus_linear(p)) { + for (int d = 0; d < dim; ++d) + { + // A. if the linear velocity is given by the user, is needs NOT to be set + if (!m_spCutElementHandler->get_DoF_modus_linear(p)) { solution = DoFRef(u, transInd[d]); - m_spParticleHandlerGlobal->set_extraSolTrans(solution, p, 0, d); - UG_LOG("transSol = " << solution << "\n"); - } + m_spCutElementHandler->set_extraSolTrans(solution, p, 0, d); + } - // B. if the angular velocity is given by the user, is needs NOT to be set - if (!m_spParticleHandlerGlobal->get_DoF_modus_angular(p)) { + // B. if the angular velocity is given by the user, is needs NOT to be set + if (!m_spCutElementHandler->get_DoF_modus_angular(p)) { solution = DoFRef(u, rotInd[d]); - m_spParticleHandlerGlobal->set_extraSolRot(solution, p, 0, d); - UG_LOG("rotSol = " << solution << "\n"); - } + m_spCutElementHandler->set_extraSolRot(solution, p, 0, d); + } } -#ifdef UG_DEBUG - UG_LOG( - "NACHHER: modify_GlobalSol transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); - UG_LOG( - "NACHHER: modify_GlobalSol transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); - UG_LOG( - "NACHHER: modify_GlobalSol rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); - UG_LOG( - "NACHHER: modify_GlobalSol rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); -#endif + if (output ){ + UG_LOG("NACHHER: modify_GlobalSol transSol(0) = " << m_spCutElementHandler->get_transSol(p,0) << "\n"); + UG_LOG("NACHHER: modify_GlobalSol transSol(1) = " << m_spCutElementHandler->get_transSol(p, 1) << "\n"); + UG_LOG("NACHHER: modify_GlobalSol rotSol(0) = " << m_spCutElementHandler->get_rotSol(p,0) << "\n"); + UG_LOG("NACHHER: modify_GlobalSol rot1Sol(1) = " << m_spCutElementHandler->get_rotSol(p, 1) << "\n"); + } } // end particle loop } template -void ParticleMapper::map_local_data(LocalVector& d) { +void ParticleMapper:: +map_local_data(LocalVector& d) +{ LocalIndices ind = d.get_indices(); // initialize tmp data @@ -455,11 +396,11 @@ template void ParticleMapper:: modify_LocalData(LocalMatrix& locJ, LocalVector& locU, ConstSmartPtr dd) { -// A. INSIDE_DOM: do nothing +// INSIDE_DOM: do nothing if (m_spInterfaceHandlerLocal->elementModus() == INSIDE_DOM) return; -// B. resize local indices: +// resize local indices: if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE && m_spInterfaceHandlerLocal->interface_id_all().size() == 2) { @@ -471,7 +412,7 @@ modify_LocalData(LocalMatrix& locJ, LocalVector& locU, ConstSmartPtrget_local_indices(); locU.resize(ind); locJ.resize(ind); @@ -480,15 +421,17 @@ modify_LocalData(LocalMatrix& locJ, LocalVector& locU, ConstSmartPtr -void ParticleMapper::modify_LocalData( - LocalVectorTimeSeries& uT, LocalMatrix& locJ, LocalVector& locU, - ConstSmartPtr dd) { - // A. INSIDE_DOM: do nothing +void ParticleMapper:: +modify_LocalData(LocalVectorTimeSeries& uT, LocalMatrix& locJ, LocalVector& locU, + ConstSmartPtr dd) +{ +// INSIDE_DOM: do nothing if (m_spInterfaceHandlerLocal->elementModus() == INSIDE_DOM) return; - for (int i = uT.size() - 1; i >= 0; --i) { - // resize local indices: + for (int i = uT.size() - 1; i >= 0; --i) + { + // resize local indices: if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE && m_spInterfaceHandlerLocal->interface_id_all().size() == 2) { if (!m_spInterfaceHandlerLocal->StdFV_assembling()) @@ -498,7 +441,7 @@ void ParticleMapper::modify_LocalData( } else resize_local_indices(locU); - // resize local data: + // resize local data: const LocalIndices& ind = m_spInterfaceHandlerLocal->get_local_indices(); locU.resize(ind); @@ -511,29 +454,29 @@ void ParticleMapper::modify_LocalData( } template -void ParticleMapper::set_QuadriSol(LocalVector& locU, - LocalVector& locD) { +void ParticleMapper:: +set_QuadriSol(LocalVector& locU, LocalVector& locD) +{ if (locU.num_all_dof(0) != 5) UG_THROW( "ParticleMapper:set_QuadriSol(): number of DoFs should be 5, but is " << locU.num_all_dof(0) << "\n"); // 3. get velocities of the 2 particles: - MathVector transSol1 = m_spParticleHandlerGlobal->get_transSol(0, 0); - MathVector rotSol1 = m_spParticleHandlerGlobal->get_rotSol(0, 0); - MathVector transSol2 = m_spParticleHandlerGlobal->get_transSol(1, 0); - MathVector rotSol2 = m_spParticleHandlerGlobal->get_rotSol(1, 0); + MathVector transSol1 = m_spCutElementHandler->get_transSol(0, 0); + MathVector rotSol1 = m_spCutElementHandler->get_rotSol(0, 0); + MathVector transSol2 = m_spCutElementHandler->get_transSol(1, 0); + MathVector rotSol2 = m_spCutElementHandler->get_rotSol(1, 0); // resize local data as done during 'modify_LocalData' // --> but there with num_co = 3 for the Triangle with inside node! for (size_t fct = 0; fct < locU.num_fct() - 1; ++fct) for (size_t dof = 0; dof < locU.num_all_dof(fct); ++dof) { MathMatrix rotationMatCo = - m_spParticleHandlerGlobal->get_rotationMat( + m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_co(dof)); - UG_LOG( - "radial(" << dof << ": " << m_spInterfaceHandlerLocal->radial_at_co(dof) << "\n"); + UG_LOG("radial(" << dof << ": " << m_spInterfaceHandlerLocal->radial_at_co(dof) << "\n"); // write solution of particle with prtIndex = 0: if (dof < 2) { @@ -554,22 +497,26 @@ void ParticleMapper::set_QuadriSol(LocalVector& locU, UG_LOG("after set_QuadriSol: locU = \n" << locU << "\n"); UG_LOG("after set_QuadriSol: locD = \n" << locD << "\n"); - UG_LOG( - "after set_QuadriSol: m_quadriLocU = \n" << m_spInterfaceHandlerLocal->m_quadriLocU << "\n"); - UG_LOG( - "after set_QuadriSol: m_quadriLocD = \n" << m_spInterfaceHandlerLocal->m_quadriLocD << "\n"); + UG_LOG("after set_QuadriSol: m_quadriLocU = \n" << m_spInterfaceHandlerLocal->m_quadriLocU << "\n"); + UG_LOG("after set_QuadriSol: m_quadriLocD = \n" << m_spInterfaceHandlerLocal->m_quadriLocD << "\n"); } template -void ParticleMapper::modify_LocalData(LocalVector& locD, +void ParticleMapper:: +modify_LocalData(LocalVector& locD, LocalVector& tmpLocD, LocalVector& locU, - ConstSmartPtr dd) { - // A. INSIDE_DOM: do nothing + ConstSmartPtr dd) +{ +/////////////////////////////////////////////////////////////////////////////// +// A. INSIDE_DOM: do nothing if (m_spInterfaceHandlerLocal->elementModus() == INSIDE_DOM) return; - // resize local indices: +/////////////////////////////////////////////////////////////////////////////// +// B. Resize local data: for QUADRILATERALS (2d) or HEXA, PRISM, PYRAMID (3d) + +// resize local indices: if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE && m_spInterfaceHandlerLocal->interface_id_all().size() == 2) { if (!m_spInterfaceHandlerLocal->StdFV_assembling()) @@ -584,30 +531,26 @@ void ParticleMapper::modify_LocalData(LocalVector& locD, locU.resize(ind); locD.resize(ind); tmpLocD.resize(ind); -// UG_LOG("---> locD = \n" << locD << "\n"); -// UG_LOG("---> locU = \n" << locU << "\n"); - // ToDo: domainDisc::adjust_solution() globally via domainDisc or Constraint! +/////////////////////////////////////////////////////////////////////////////// +// C. Write the particle rigid body velocity into resized solution 'locU' + int prtIndex = get_prtIndex(); + const MathVector center = m_spCutElementHandler->get_center(prtIndex); - const MathVector center = m_spParticleHandlerGlobal->get_center( - prtIndex); + MathVector transSol = m_spCutElementHandler->get_transSol(prtIndex,0); + MathVector rotSol = m_spCutElementHandler->get_rotSol(prtIndex, 0); - MathVector transSol = m_spParticleHandlerGlobal->get_transSol(prtIndex, - 0); - MathVector rotSol = m_spParticleHandlerGlobal->get_rotSol(prtIndex, 0); - -// B. OUTSIDE_DOM: write solution for ALL corners +// OUTSIDE_DOM: write solution for ALL corners if (m_spInterfaceHandlerLocal->elementModus() == OUTSIDE_DOM) { for (size_t fct = 0; fct < locU.num_fct() - 1; ++fct) for (size_t dof = 0; dof < locU.num_all_dof(fct); ++dof) { - //MathMatrix rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->corner(dof)); MathVector radialCo; VecSubtract(radialCo, m_spInterfaceHandlerLocal->corner(dof), center); MathMatrix rotationMatCo = - m_spParticleHandlerGlobal->get_rotationMat(radialCo); + m_spCutElementHandler->get_rotationMat(radialCo); // set solution locU(fct, dof) = transSol[fct]; @@ -617,13 +560,12 @@ void ParticleMapper::modify_LocalData(LocalVector& locD, } } -// C. CUT_BY_INTERFACE: write solution for interface corners +// CUT_BY_INTERFACE: write solution for interface corners if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_INTERFACE || (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE && m_spInterfaceHandlerLocal->StdFV_assembling())) { map_local_data(locU); - //for(size_t fct=0; fct < locU.num_fct()-1; ++fct) // VORSICHT: locU.num_fct() = 1 fuer shear_interface...warum auch immer... for (size_t fct = 0; fct < locU.num_fct() - 1; ++fct) { for (size_t i = 0; i < m_spInterfaceHandlerLocal->interface_id_all().size(); @@ -631,11 +573,11 @@ void ParticleMapper::modify_LocalData(LocalVector& locD, size_t interfaceID = m_spInterfaceHandlerLocal->interface_id(i); MathMatrix rotationMatCo = - m_spParticleHandlerGlobal->get_rotationMat( + m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_co( interfaceID)); - // set solution + // set solution locU(fct, interfaceID) = transSol[fct]; for (int d = 0; d < dim; ++d) @@ -645,7 +587,7 @@ void ParticleMapper::modify_LocalData(LocalVector& locD, } } -// D. CUT_BY_2_INTERFACE: +// CUT_BY_2_INTERFACE: if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE) { if (!m_spInterfaceHandlerLocal->StdFV_assembling()) set_QuadriSol(locU, locD); @@ -654,24 +596,26 @@ void ParticleMapper::modify_LocalData(LocalVector& locD, } template -void ParticleMapper::modify_LocalData( +void ParticleMapper:: +modify_LocalData( LocalVectorTimeSeries& uT, LocalVector& locD, LocalVector& tmpLocD, - LocalVector& locU, ConstSmartPtr dd, size_t t) { + LocalVector& locU, ConstSmartPtr dd, size_t t) +{ // 'modify_LocalData()' is called twice (for t=0, t=1) in elem_disc_assemble_util; // BUT: 'map_local_data()' may be called only once! if (t == 1) return; - // A. INSIDE_DOM: do nothing +/////////////////////////////////////////////////////////////////////////////// +// A. INSIDE_DOM: do nothing + if (m_spInterfaceHandlerLocal->elementModus() == INSIDE_DOM) return; - - // ToDo: domainDisc::adjust_solution() globally via domainDisc or Constraint! - int prtIndex = get_prtIndex(); - const MathVector center = m_spParticleHandlerGlobal->get_center( - prtIndex); - + +/////////////////////////////////////////////////////////////////////////////// +// B. Resize local data: for QUADRILATERALS (2d) or HEXA, PRISM, PYRAMID (3d) + // resize local indices: if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE && m_spInterfaceHandlerLocal->interface_id_all().size() == 2) { @@ -688,19 +632,23 @@ void ParticleMapper::modify_LocalData( locD.resize(ind); tmpLocD.resize(ind); - // loop all time points and assemble them +/////////////////////////////////////////////////////////////////////////////// +// C. Write the particle rigid body velocity into resized solution 'locU' + + int prtIndex = get_prtIndex(); + const MathVector center = m_spCutElementHandler->get_center(prtIndex); + +// loop all time points and assemble them for (int i = uT.size() - 1; i >= 0; --i) { uT.solution(i).resize(ind); LocalVector* vecMod = &uT.solution(i); - MathVector transSol = m_spParticleHandlerGlobal->get_transSol( - prtIndex, i); - MathVector rotSol = m_spParticleHandlerGlobal->get_rotSol(prtIndex, - i); + MathVector transSol = m_spCutElementHandler->get_transSol(prtIndex, i); + MathVector rotSol = m_spCutElementHandler->get_rotSol(prtIndex,i); - // B. OUTSIDE_DOM: write solution for ALL corners + // OUTSIDE_DOM: write solution for ALL corners if (m_spInterfaceHandlerLocal->elementModus() == OUTSIDE_DOM) { for (size_t fct = 0; fct < locU.num_fct() - 1; ++fct) for (size_t dof = 0; dof < locU.num_all_dof(fct); ++dof) { @@ -708,10 +656,10 @@ void ParticleMapper::modify_LocalData( VecSubtract(radialCo, m_spInterfaceHandlerLocal->corner(dof), center); MathMatrix rotationMatCo = - m_spParticleHandlerGlobal->get_rotationMat( + m_spCutElementHandler->get_rotationMat( radialCo); - // set solution + // set solution (*vecMod)(fct, dof) = transSol[fct]; for (int d = 0; d < dim; ++d) (*vecMod)(fct, dof) += rotationMatCo[fct][d] @@ -720,7 +668,7 @@ void ParticleMapper::modify_LocalData( } } - // C. CUT_BY_INTERFACE: write solution for interface corners + // CUT_BY_INTERFACE: write solution for interface corners if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_INTERFACE || (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE @@ -734,11 +682,11 @@ void ParticleMapper::modify_LocalData( size_t interfaceID = m_spInterfaceHandlerLocal->interface_id(i); MathMatrix rotationMatCo = - m_spParticleHandlerGlobal->get_rotationMat( + m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_co( interfaceID)); - // set solution + // set solution (*vecMod)(fct, interfaceID) = transSol[fct]; for (int d = 0; d < dim; ++d) (*vecMod)(fct, interfaceID) += rotationMatCo[fct][d] @@ -748,7 +696,7 @@ void ParticleMapper::modify_LocalData( } - // D. CUT_BY_2_INTERFACE: + // CUT_BY_2_INTERFACE: if (m_spInterfaceHandlerLocal->elementModus() == CUT_BY_2_INTERFACE) { if (!m_spInterfaceHandlerLocal->StdFV_assembling()) UG_THROW("modify_LocalData(): CUT_BY_2_INTERFACE\n"); //set_QuadriSol(locU, locD); @@ -758,73 +706,6 @@ void ParticleMapper::modify_LocalData( } -/* - template < typename TDomain, typename TAlgebra> - void ParticleMapper:: - modify_LocalSol(SmartPtr vSolMod, - ConstSmartPtr vSol, ConstSmartPtr dd) - { - // check current and old solution - if(vSol->size() != 2) - UG_THROW("ParParticleMapperticle::modify_LocalSol: " - " Stabilization needs exactly two time points."); - - // A. INSIDE_DOM: do nothing - if(m_spInterfaceHandlerLocal->elementModus() == INSIDE_DOM) - return; - - // ToDo: domainDisc::adjust_solution() globally via domainDisc or Constraint! - int prtIndex = get_prtIndex(); - - // loop all time points and assemble them - for(int i = vSol->size()-1; i >= 0 ; --i) - { - MathVector transSol = m_spParticleHandlerGlobal->get_transSol(prtIndex, i); - MathVector rotSol = m_spParticleHandlerGlobal->get_rotSol(prtIndex, i); - - LocalVector* vecMod = &vSolMod->solution(i); - - // B. OUTSIDE_DOM: write solution for ALL corners - if(m_spInterfaceHandlerLocal->elementModus() == OUTSIDE_DOM) - { - for(size_t fct = 0; fct < dim; ++fct) - for(size_t dof=0; dof < vecMod->num_all_dof(fct); ++dof) - { - MathMatrix rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->corner(dof)); - - // set solution - (*vecMod)(fct,dof) = transSol[fct]; - for ( int d = 0; d < dim; ++d ) - (*vecMod)(fct,dof) += rotationMatCo[fct][d]*rotSol[d]; - - } - } - - // C. CUT_BY_INTERFACE: write solution for interface corners - if(m_spInterfaceHandlerLocal->elementModus() == CUT_BY_INTERFACE) - { - for(size_t fct = 0; fct < dim; ++fct) - for(size_t i = 0; i < m_spInterfaceHandlerLocal->interface_id_all().size(); ++i) - //for(size_t dof=0; dof < lvec.num_all_dof(fct); ++dof) - { - size_t interfaceID = m_spInterfaceHandlerLocal->interface_id(i); - size_t dof = m_spInterfaceHandlerLocal->corner_orig(interfaceID); - - MathMatrix rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(dof)); - - // set solution - (*vecMod)(fct,dof) = transSol[fct]; - for ( int d = 0; d < dim; ++d ) - (*vecMod)(fct,dof) += rotationMatCo[fct][d]*rotSol[d]; - - } - } - - } // end time loop - - } - - */ template void ParticleMapper:: @@ -842,13 +723,13 @@ set_identity_mat_constraint(matrix_type& mat, const LocalMatrix& lmat, ConstSmar const size_t rowIndex = rowInd.index(fct1, _dof1); const size_t rowComp = rowInd.comp(fct1, _dof1); - // m_spParticleHandlerGlobal->is_extraDoF returns false, if particle velocity is given by the model - bool is_extraDoF = m_spParticleHandlerGlobal->is_extraDoF( + // m_spCutElementHandler->is_extraDoF returns false, if particle velocity is given by the model + bool is_extraDoF = m_spCutElementHandler->is_extraDoF( DoFIndex(rowIndex, rowComp), levIndex); - // IFF node is no transInd/rotInd-node and no interface node! + // IFF node is no transInd/rotInd-node and no interface node! bool is_interfaceDoF = true; - // on interface, only pressure is real DoF: + // on interface, only pressure is real DoF: if (fct1 != dim) is_interfaceDoF = false; else if (m_spInterfaceHandlerLocal->StdFV_assembling()) { @@ -863,7 +744,7 @@ set_identity_mat_constraint(matrix_type& mat, const LocalMatrix& lmat, ConstSmar m_spInterfaceHandlerLocal->remapped_fromInterface( _dof1); - // DoFs on interface OR for translational/angular velocity need to remain free + // DoFs on interface OR for translational/angular velocity need to remain free if (is_interfaceDoF || is_extraDoF) continue; else @@ -873,46 +754,27 @@ set_identity_mat_constraint(matrix_type& mat, const LocalMatrix& lmat, ConstSmar } template -void ParticleMapper::add_local_mat_to_global( - matrix_type& mat, const LocalMatrix& lmat, - ConstSmartPtr dd) { - /* ATTENTION: - * 'mat' contains entries for ALL ElemDiscs! - * But: apply add_local_mat_to_global_interface() only for - * (some) specified ElemDiscs! - * - * solution A: 1. map via 'acess_by_map(m_pElemDisc->map())' - * 2. set mat(access_by_map()-indices) to zero - * 3. apply usual AddLocalMatrixToGlobal() - * - * solution B: vElemDisc-loop as in DataEvaluator: - * // compute elem-owned mapping - try{ - for(size_t i = 0; i < m_vElemDisc[type].size(); ++i) - m_vElemDisc[type][i]->do_add_jac_A_elem(J, u, elem, vCornerCoords); - } - - solution C: AssemblingTuner becomes also member of IElemDisc, - NOT DomainDisc - */ - +void ParticleMapper:: +add_local_mat_to_global(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd) +{ +// reset print modus for cut element data to 'false' +// => only printed during assemling of defect, i.e. ONE loop over all element + m_spInterfaceHandlerLocal->set_print_cutElemData(false); + ElementModus modus = m_spInterfaceHandlerLocal->elementModus(); LocalMatrix locJ = lmat; switch (modus) { - case OUTSIDE_DOM: - map_all_local_mat_to_transDoF(mat, lmat, dd); // hier steht mass term aus 'add_jac_M_elem()' - if (0) //m_spInterfaceHandlerLocal->StdFV_assembling() ) - add_local_mat_to_global_interface(mat, lmat, dd); - set_identity_mat_constraint(mat, lmat, dd); //IFF element does NOT include transInd/rotInd-node! + case OUTSIDE_DOM: // no DoFs: set identity-rows + set_identity_mat_constraint(mat, lmat, dd); //IFF element does NOT include transInd/rotInd-node! break; - case INSIDE_DOM: + case INSIDE_DOM: // call usual local-to-global-mapping AddLocalMatrixToGlobal(mat, lmat); break; - case CUT_BY_INTERFACE: + case CUT_BY_INTERFACE: // call adapted local-to-global-mapping add_local_mat_to_global_interface(mat, lmat, dd); break; - case CUT_BY_2_INTERFACE: + case CUT_BY_2_INTERFACE: // call adapted local-to-global-mapping add_local_mat_to_global_interface_for2(mat, lmat, dd); break; default: @@ -923,29 +785,23 @@ void ParticleMapper::add_local_mat_to_global( } template -void ParticleMapper::add_local_vec_to_global( - vector_type& vec, const LocalVector& lvec, +void ParticleMapper:: +add_local_vec_to_global(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd) { ElementModus modus = m_spInterfaceHandlerLocal->elementModus(); switch (modus) { - case OUTSIDE_DOM: - if (0) //m_spInterfaceHandlerLocal->StdFV_assembling() ) - add_local_vec_to_global_interface(vec, lvec, dd); - // add nothing; ?? - // ToDo map_all_local_vec_to_transDoF(vec, lvec, dd); // hier steht jetzt timedep. gravity force aus 'add_def_A_elem()' - // _A_ und NICHT _M_, da zeit faktor notwendig! - // set_zero_defect(); --> NOT necessary, since NO adding => 0.0 + case OUTSIDE_DOM: // no DoFs: no contribution to defect break; - case INSIDE_DOM: + case INSIDE_DOM: // call usual local-to-global-mapping AddLocalVector(vec, lvec); break; - case CUT_BY_INTERFACE: + case CUT_BY_INTERFACE: // call adapted local-to-global-mapping add_local_vec_to_global_interface(vec, lvec, dd); break; - case CUT_BY_2_INTERFACE: + case CUT_BY_2_INTERFACE: // call adapted local-to-global-mapping add_local_vec_to_global_interface_for2(vec, lvec, dd); break; default: @@ -959,7 +815,8 @@ void ParticleMapper::add_local_vec_to_global( template void ParticleMapper:: add_mass_part_jac(matrix_type& mat, std::vector transInd, std::vector rotInd, - const int levIndex, const int prtIndex) { + const int levIndex, const int prtIndex) +{ number volume; if (m_bVolumeCompExact) @@ -967,343 +824,98 @@ add_mass_part_jac(matrix_type& mat, std::vector transInd, std::vector< else volume = compute_volume(levIndex, prtIndex); - // add mass term to global matrix (instead of using IConstraint::adjust_jacobian() ) +// add mass term to global matrix (instead of using IConstraint::adjust_jacobian() ) for (int d = 0; d < dim; ++d) { - DoFRef(mat, transInd[d], transInd[d]) += Mass(levIndex, prtIndex, - volume); - // for dim = 2: the second DoF of rotInd is unused! + DoFRef(mat, transInd[d], transInd[d]) += Mass(levIndex, prtIndex, volume); + // for dim = 2: the second DoF of rotInd is unused! if (dim == 3 || d == 0) - DoFRef(mat, rotInd[d], rotInd[d]) += MomOfInertia(levIndex, - prtIndex, volume); + DoFRef(mat, rotInd[d], rotInd[d]) += MomOfInertia(levIndex, prtIndex, volume); } - if (m_bVolumeCompExact) - m_bFlagInertial[prtIndex] = false; // adding mass/inertia terms only ONCE!! -} - -// call for 'OUTSIDE_DOM' -template -void ParticleMapper::map_all_local_mat_to_transDoF( - matrix_type& mat, const LocalMatrix& lmat, - ConstSmartPtr dd) { - +// adding mass/inertia terms only ONCE!! + if (m_bVolumeCompExact) + m_bFlagInertial[prtIndex] = false; + } -/* - template - void ParticleMapper:: - add_local_mat_to_global_FT_for2(matrix_type& mat, const LocalMatrix& lmat, - std::vector transInd1, std::vector rotInd1, - std::vector transInd2, std::vector rotInd2) - { - UG_LOG("start add_local_mat_to_global_FT_for2()\n"); - - UG_LOG("transInd1: " << transInd1[0] << "\n"); - UG_LOG("transInd2: " << transInd2[0] << "\n"); - UG_LOG("rotInd1: " << rotInd1[0] << "\n"); - UG_LOG("rotInd2: " << rotInd2[0] << "\n"); - - MathMatrix rotationMatCo, rotationMatIP, rotationMatIP_transposed; - std::vector transInd_from, rotInd_from; - std::vector transInd_to, rotInd_to; - - UG_LOG("lmat.num_all_row_dof(0) = \n" << lmat.num_all_row_dof(0) << "\n"); - UG_LOG("lmat.num_all_row_dof(1) = \n" << lmat.num_all_row_dof(1) << "\n"); - if ( lmat.num_all_row_dof(0) != 4 ) - UG_THROW("lmat.num_all_row_dof(2) = \n" << lmat.num_all_row_dof(2) << "\n"); - - for(size_t fct1=0; fct1 < 2; ++fct1) - for(size_t fct2=0; fct2 < 2; ++fct2) - for(size_t dof1=0; dof1 < 4; ++dof1) - for(size_t dof2=0; dof2 < 4; ++dof2) - { - rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(dof2)); - rotationMatIP = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_ip(dof1)); - - UG_LOG("dof1: " << dof1 << ", m_spInterfaceHandlerLocal->radial_at_ip(dof1): " << m_spInterfaceHandlerLocal->radial_at_ip(dof1) << "\n"); - UG_LOG("dof2: " << dof2 << ", m_spInterfaceHandlerLocal->radial_at_co(dof2): " << m_spInterfaceHandlerLocal->radial_at_co(dof2) << "\n"); - - - // coupling FROM particle1 - if ( dof1 < 2 ) { transInd_from = transInd1; rotInd_from = rotInd1; } - // coupling FROM particle2 - else { transInd_from = transInd2; rotInd_from = rotInd2; } - // coupling TO particle1 - if ( dof2 < 2 ) { transInd_to = transInd1; rotInd_to = rotInd1; } - // coupling TO particle2 - else { transInd_to = transInd2; rotInd_to = rotInd2; } - - UG_LOG("transInd_from: " << transInd_from[0] << "\n"); - UG_LOG("rotInd_from: " << rotInd_from[0] << "\n"); - UG_LOG("transInd_to: " << transInd_to[0] << "\n"); - UG_LOG("rotInd_to: " << rotInd_to[0] << "\n"); - - UG_THROW("check it out...\n"); - - // trans-trans - DoFRef(mat, transInd_from[fct1], transInd_to[fct2]) - += lmat.value(fct1,dof1,fct2,dof2); - - // trans-rot - for ( size_t cmp = 0; cmp < dim; ++cmp ) - DoFRef(mat, transInd_from[fct1], rotInd_to[cmp]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp]; - - // rot-trans - for ( size_t cmp = 0; cmp < dim; ++cmp ) - DoFRef(mat, rotInd_from[cmp], transInd_to[fct2]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatIP[fct1][cmp]; - - // rot-rot - for ( size_t cmp1 = 0; cmp1 < dim; ++cmp1 ) - for ( size_t cmp2 = 0; cmp2 < dim; ++cmp2 ) - DoFRef(mat, rotInd_from[cmp1], rotInd_to[cmp2]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp2]*rotationMatIP[fct1][cmp1]; - - } // end dof2-loop - - - - const LocalIndices& rowInd = lmat.get_row_indices(); - const LocalIndices& colInd = lmat.get_col_indices(); - - // FIRST: assemble connections between the 2 particles - for(size_t fct1=0; fct1 < lmat.num_all_row_fct(); ++fct1) - for(size_t dof1=0; dof1 < lmat.num_all_row_dof(fct1); ++dof1) - { - const DoFIndex indexRow = DoFIndex(rowInd.index(fct1,dof1), rowInd.comp(fct1,dof1)); - - for(size_t fct2=0; fct2 < lmat.num_all_col_fct(); ++fct2) - for(size_t dof2=0; dof2 < lmat.num_all_col_dof(fct2); ++dof2) - { - const DoFIndex indexCol = DoFIndex(colInd.index(fct2,dof2), colInd.comp(fct2,dof2)); - - rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(dof2)); - rotationMatIP = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_ip(dof1)); - - Transpose(rotationMatIP_transposed, rotationMatIP); - - size_t interfaceID; - - - size_t modus = getMappingModus(fct1, dof1, fct2, dof2); - switch(modus) - { - case 0: - { - DoFRef(mat, indexRow, indexCol) - += lmat.value(fct1,dof1,fct2,dof2); - } break; - case 1: - { - // A: get DoFIndex for connection to one of the 2 particles - bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(dof2, interfaceID); - if ( interfaceID < 2 ) - { transInd_to = transInd1; rotInd_to = rotInd1; } - else - { transInd_to = transInd2; rotInd_to = rotInd2; } - - // B: finally assemble connection: - DoFRef(mat, indexRow, transInd_to[fct2]) - += lmat.value(fct1,dof1,fct2,dof2); - - for ( size_t cmp = 0; cmp < dim; ++cmp ){ - DoFRef(mat, indexRow, rotInd_to[cmp]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp]; - } - - } break; - case 2: - { - // A: get DoFIndex for connection to one of the 2 particles - bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(dof1, interfaceID); - if ( interfaceID < 2 ) - { transInd_from = transInd1; rotInd_from = rotInd1; } - else - { transInd_from = transInd2; rotInd_from = rotInd2; } - - // B: finally assemble connection: - DoFRef(mat, transInd_from[fct1], indexCol) - += lmat.value(fct1,dof1,fct2,dof2); - - for ( size_t cmp = 0; cmp < dim; ++cmp ) - { - if ( 1) //fct2 != dim ) - { - DoFRef(mat, rotInd_from[cmp], indexCol) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatIP[fct1][cmp]; - } - } - - } break; - case 3: - { - // A: get DoFIndex for connection to one of the 2 particles - bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(dof1, interfaceID); - if ( interfaceID < 2 ) - { transInd_from = transInd1; rotInd_from = rotInd1; } - else - { transInd_from = transInd2; rotInd_from = rotInd2; } - - isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(dof2, interfaceID); - if ( interfaceID < 2 ) - { transInd_to = transInd1; rotInd_to = rotInd1; } - else - { transInd_to = transInd2; rotInd_to = rotInd2; } - - // B: finally assemble connection: - // trans-trans - DoFRef(mat, transInd_from[fct1], transInd_to[fct2]) - += lmat.value(fct1,dof1,fct2,dof2); - - // trans-rot ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) - for ( size_t cmp = 0; cmp < dim; ++cmp ) - DoFRef(mat, transInd_from[fct1], rotInd_to[cmp]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp]; - for ( size_t cmp = 0; cmp < dim; ++cmp ) - DoFRef(mat, rotInd_from[cmp], transInd_to[fct2]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatIP[fct1][cmp]; - - - for ( size_t cmp1 = 0; cmp1 < dim; ++cmp1 ) - for ( size_t cmp2 = 0; cmp2 < dim; ++cmp2 ) - DoFRef(mat, rotInd_from[cmp1], rotInd_to[cmp2]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp2]*rotationMatIP[fct1][cmp1]; - - } - break; - case 4:{// to pressure outside: sum = e-20 => skip! - } - break; - - default: - throw(UGError("Error in LocToGlob!")); - - } // end switch-cases - - } // end dof2-loop - - //////////////////////////////////////////////////////////////////////////////////////////////// - // finally set dirichlet row for velocity DoFs on interface: - // ---> also done during 'set_identity_mat_constraint()', BUT only for OUTSIDE_DOM-elements!! - //////////////////////////////////////////////////////////////////////////////////////////////// - - } // end dof1-loop - - - - if (0 ) // m_spInterfaceHandlerLocal->interface_id_all().size() == 4 ) - UG_THROW("end add_local_mat_to_gloabal_FT_for2()\n\n"); - - - } - */ - // call for 'CUT_BY_2_INTERFACE' template -void ParticleMapper::add_local_mat_to_global_interface_for2( - matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd) +void ParticleMapper:: +add_local_mat_to_global_interface_for2(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd) { +// REMARK: not finally tested! + UG_THROW("ParticleMapper::add_local_mat_to_global_interface_for2(): not finally tested!!!!\n"); + // get data const int levIndex = get_Index(dd->grid_level(), dd); std::vector < DoFIndex > transInd1, rotInd1, transInd2, rotInd2; - m_spParticleHandlerGlobal->get_global_indices(transInd1, rotInd1, levIndex, - 0); - m_spParticleHandlerGlobal->get_global_indices(transInd2, rotInd2, levIndex, - 1); - - UG_LOG( - "____________________________________________________________________\n"); - - for (size_t i = 0; i < m_spInterfaceHandlerLocal->m_vCornerCoords.size(); - ++i) - UG_LOG( - "m_vCornerCoords = " << m_spInterfaceHandlerLocal->m_vCornerCoords[i] << "\n"); - for (size_t i = 0; - i < m_spInterfaceHandlerLocal->m_vOriginalCornerID.size(); ++i) - UG_LOG( - "Original: id = " << m_spInterfaceHandlerLocal->m_vOriginalCornerID[i] << "\n"); - UG_LOG("\n"); - for (size_t i = 0; i < m_spInterfaceHandlerLocal->m_vInterfaceID.size(); - ++i) - UG_LOG( - "Interface: id = " << m_spInterfaceHandlerLocal->m_vInterfaceID[i] << "\n"); - UG_LOG("\n"); - - UG_LOG( - "____________________________________________________________________\n"); + m_spCutElementHandler->get_global_indices(transInd1, rotInd1, levIndex,0); + m_spCutElementHandler->get_global_indices(transInd2, rotInd2, levIndex,1); + if (!UsualAss()) + { if (m_spInterfaceHandlerLocal->StdFV_assembling()) add_local_mat_to_global_FT_for2_StdFV(mat, lmat, transInd1, rotInd1, transInd2, rotInd2); else add_local_mat_to_global_FT_for2(mat, lmat, transInd1, rotInd1, transInd2, rotInd2); - else - UG_THROW( - "add_local_mat_to_global_interface_for2(): -> not implemented!\n"); - + } + else { + UG_THROW("add_local_mat_to_global_interface_for2(): -> not implemented!\n"); + } } // call for 'CUT_BY_INTERFACE' template -void ParticleMapper::add_local_mat_to_global_interface( - matrix_type& mat, const LocalMatrix& lmat, - ConstSmartPtr dd) { +void ParticleMapper:: +add_local_mat_to_global_interface(matrix_type& mat, const LocalMatrix& lmat, + ConstSmartPtr dd) +{ // get data const int levIndex = get_Index(dd->grid_level(), dd); int prtIndex = get_prtIndex(); -/* // Attention: call for 'getprtIndex()'-method of 'InterfaceHandlerLocalParticle', i.e. simply 'get_prtIndex()' - // because: m_spParticleHandlerGlobal->get_prtIndex(-> size_t dof <-) calls 'getprtIndex()'-method of 'CutElementHander', - // which contains an array, which is not allready implemented to be filled during computation!! - // (only necessary for more than 1 particle cutting an element!) - - int prtIndex = m_spParticleHandlerGlobal->get_prtIndex(0); - if (prtIndex == -1) - prtIndex = m_spParticleHandlerGlobal->get_prtIndex(1); - if (prtIndex == -1) - prtIndex = m_spParticleHandlerGlobal->get_prtIndex(2); -*/ std::vector < DoFIndex > transInd, rotInd; - m_spParticleHandlerGlobal->get_global_indices(transInd, rotInd, levIndex, - prtIndex); + m_spCutElementHandler->get_global_indices(transInd, rotInd, levIndex, prtIndex); // A. add mass part to jacobian if (m_bFlagInertial[prtIndex]) add_mass_part_jac(mat, transInd, rotInd, levIndex, prtIndex); // B. add local to global - if (!UsualAss()) + if (!UsualAss()){ add_local_mat_to_global_FT(mat, lmat, transInd, rotInd); - //else - // ToDo add_local_mat_to_global_usual(mat, lmat, dd); + } + else { + UG_THROW("ParticleMapper::add_local_mat_to_global_usual(): -> not implemented!\n"); + } + } template -void ParticleMapper::add_glowinski_repulsive_force_rhs(vector_type& vec, - std::vector transInd, std::vector rotInd, - const int levIndex, const int prtIndex) +void ParticleMapper:: +add_glowinski_repulsive_force_rhs(vector_type& vec, std::vector transInd, + std::vector rotInd,const int levIndex, const int prtIndex) { - //UG_LOG("add_repulsive_force \n"); - //////////////////////////////////////////////////////////////// - // compute repulsive force: - //////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +// compute repulsive force: +//////////////////////////////////////////////////////////////// for (size_t i = 0; i < num_particles(); ++i) { - if (i == prtIndex) {continue;} - // Get particle values - MathVector center_i = m_spParticleHandlerGlobal->get_center(i); - MathVector center_prtIndex = m_spParticleHandlerGlobal->get_center(prtIndex); + if ((int)i == prtIndex) {continue;} + // Get particle values + MathVector center_i = m_spCutElementHandler->get_center(i); + MathVector center_prtIndex = m_spCutElementHandler->get_center(prtIndex); double Mass_i = Mass(levIndex,i); double Mass_prtIndex = Mass(levIndex,prtIndex); - // Calculate distance vector between center points + // Calculate distance vector between center points double dist = 0; for (size_t d = 0; d < dim; ++d){ dist += (center_i[d]-center_prtIndex[d])*(center_i[d]-center_prtIndex[d]); @@ -1313,12 +925,12 @@ void ParticleMapper::add_glowinski_repulsive_force_rhs(vector distanceVec -= center_i; distanceVec /= dist; - // Calculate force + // Calculate force double force = (Mass_i+Mass_prtIndex)/2*981/(0.5*m_epsilon); - double max1 = std::max(0.0,-(dist-m_spParticleHandlerGlobal->get_radius(i)-m_spParticleHandlerGlobal->get_radius(prtIndex)-m_rho)/(m_rho)); + double max1 = std::max(0.0,-(dist-m_spCutElementHandler->get_radius(i)-m_spCutElementHandler->get_radius(prtIndex)-m_rho)/(m_rho)); force *= pow(max1,2); - // Scale with time step + // Scale with time step number timeScale = 1.0; if (is_time_dependent()) { timeScale = m_dt; @@ -1340,30 +952,29 @@ void ParticleMapper::add_glowinski_repulsive_force_rhs(vector } template -void ParticleMapper::add_minimum_correction_force_rhs(vector_type& vec, - std::vector transInd, std::vector rotInd, - const int levIndex, const int prtIndex) +void ParticleMapper:: +add_minimum_correction_force_rhs(vector_type& vec,std::vector transInd, + std::vector rotInd, const int levIndex, const int prtIndex) { - //UG_LOG("add_repulsive_force \n"); - //////////////////////////////////////////////////////////////// - // compute repulsive force: - //////////////////////////////////////////////////////////////// - // if (!m_spParticleHandlerGlobal->valid_prt_information(i)) { +//////////////////////////////////////////////////////////////// +// compute repulsive force: +//////////////////////////////////////////////////////////////// + // if (!m_spCutElementHandler->valid_prt_information(i)) { // return; // } for (size_t i = 0; i < num_particles(); ++i) { - if (!m_bGlowRepulsiveForce && (i != prtIndex)) { + if (!m_bGlowRepulsiveForce && ((int)i != prtIndex)) { // Do not calc force with outdated particle informations - if (i == prtIndex) {continue;} - // Get particle values - MathVector center_i = m_spParticleHandlerGlobal->get_center(i); - MathVector center_prtIndex = m_spParticleHandlerGlobal->get_center(prtIndex); + if ((int)i == prtIndex) {continue;} + // Get particle values + MathVector center_i = m_spCutElementHandler->get_center(i); + MathVector center_prtIndex = m_spCutElementHandler->get_center(prtIndex); double Mass_i = Mass(levIndex,i); double Mass_prtIndex = Mass(levIndex,prtIndex); - // Calculate distance vector between center points + // Calculate distance vector between center points double dist = 0; for (size_t d = 0; d < dim; ++d){ dist += (center_i[d]-center_prtIndex[d])*(center_i[d]-center_prtIndex[d]); @@ -1380,12 +991,12 @@ void ParticleMapper::add_minimum_correction_force_rhs(vector_ } } - // Calculate force + // Calculate force double force = (Mass_i+Mass_prtIndex)/2*981/(m_epsilon); - double max1 = std::max(0.0,-(dist-m_spParticleHandlerGlobal->get_radius(i)-m_spParticleHandlerGlobal->get_radius(prtIndex)-m_rho)/(m_rho)); + double max1 = std::max(0.0,-(dist-m_spCutElementHandler->get_radius(i)-m_spCutElementHandler->get_radius(prtIndex)-m_rho)/(m_rho)); force *= pow(max1,2); - // Scale with time step + // Scale with time step number timeScale = 1.0; if (is_time_dependent()) { timeScale = m_dt; @@ -1399,14 +1010,14 @@ void ParticleMapper::add_minimum_correction_force_rhs(vector_ } if (m_bMinimumCorrectionForce){ - if (i == prtIndex) {continue;} - // Get particle values - MathVector center_i = m_spParticleHandlerGlobal->get_center(i); - MathVector center_prtIndex = m_spParticleHandlerGlobal->get_center(prtIndex); + if ((int)i == prtIndex) {continue;} + // Get particle values + MathVector center_i = m_spCutElementHandler->get_center(i); + MathVector center_prtIndex = m_spCutElementHandler->get_center(prtIndex); double Mass_i = Mass(levIndex,i); double Mass_prtIndex = Mass(levIndex,prtIndex); - // Calculate distance vector between center points + // Calculate distance vector between center points double dist = 0; for (size_t d = 0; d < dim; ++d){ dist += (center_i[d]-center_prtIndex[d])*(center_i[d]-center_prtIndex[d]); @@ -1421,7 +1032,7 @@ void ParticleMapper::add_minimum_correction_force_rhs(vector_ // double force = Delta_r/2 * 1/(m_rho*m_rho); - // Scale with time step + // Scale with time step number timeScale = 1.0; if (is_time_dependent()) { timeScale = m_dt; @@ -1441,11 +1052,10 @@ void ParticleMapper::add_minimum_correction_force_rhs(vector_ } template -void ParticleMapper::add_repulsive_force_rhs(vector_type& vec, - std::vector transInd, std::vector rotInd, - const int levIndex, const int prtIndex) +void ParticleMapper:: +add_repulsive_force_rhs(vector_type& vec, std::vector transInd, + std::vector rotInd, const int levIndex, const int prtIndex) { - //UG_LOG("add_repulsive_force \n"); //////////////////////////////////////////////////////////////// // compute repulsive force: //////////////////////////////////////////////////////////////// @@ -1453,14 +1063,14 @@ void ParticleMapper::add_repulsive_force_rhs(vector_type& vec double force = m_repulsiveForce; for (size_t i = 0; i < num_particles(); ++i) { - if (i == prtIndex) {continue;} - // Get particle values - MathVector center_i = m_spParticleHandlerGlobal->get_center(i); - MathVector center_prtIndex = m_spParticleHandlerGlobal->get_center(prtIndex); - double Mass_i = Mass(levIndex,i); + if ((int)i == prtIndex) {continue;} + // Get particle values + MathVector center_i = m_spCutElementHandler->get_center(i); + MathVector center_prtIndex = m_spCutElementHandler->get_center(prtIndex); + // double Mass_i = Mass(levIndex,i); double Mass_prtIndex = Mass(levIndex,prtIndex); - // Calculate distance vector between center points + // Calculate distance vector between center points double dist = 0; for (size_t d = 0; d < dim; ++d){ dist += (center_i[d]-center_prtIndex[d])*(center_i[d]-center_prtIndex[d]); @@ -1471,7 +1081,7 @@ void ParticleMapper::add_repulsive_force_rhs(vector_type& vec distanceVec /= dist; UG_LOG("Unscaled equivalent repulsive force is "<::add_repulsive_force_rhs(vector_type& vec template -void ParticleMapper::set_gravitational_rhs(vector_type& vec, - std::vector transInd, std::vector rotInd, +void ParticleMapper:: +set_gravitational_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, const int levIndex, const int prtIndex) { + bool logGravity = false; + // some initial checks: Parameters need to be set via lua-script! if (m_gravityConst == 0.0) UG_THROW("m_gravityConst not defined!\n"); if (is_time_dependent() && m_dt == 0.0) UG_THROW("time step 'm_dt' not defined! Needs to be set via lua-script: 'set_time_step(dt)'...\n"); - - bool logGravity = true; - if (logGravity) { UG_LOG("//////////////////////////////// - log_Gravity (" << prtIndex << ") - ///////////////////////////////\n"); @@ -1553,14 +1162,12 @@ void ParticleMapper::set_gravitational_rhs(vector_type& vec, if (logGravity) { UG_LOG("gravitationalMass: " << gravitationalMass << "\n"); - UG_LOG("gravForce added: " << gravityForce << "dt: " << m_dt <<"\n"); UG_LOG("//////////////////////////////// - log_Gravity - ///////////////////////////////\n"); UG_LOG("NACHHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); UG_LOG("NACHHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); if (dim == 3) UG_LOG("NACCHHER: defect(trans,2): " << DoFRef(vec, transInd[2]) << "\n"); - UG_LOG("NACHHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); UG_LOG("NACHHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); if (dim == 3) @@ -1569,36 +1176,26 @@ void ParticleMapper::set_gravitational_rhs(vector_type& vec, } -// call for 'OUTSIDE_DOM' -template -void ParticleMapper::map_all_local_vec_to_transDoF( - vector_type& vec, const LocalVector& lvec, - ConstSmartPtr dd) { - -} template -void ParticleMapper::add_mass_part_def(vector_type& vec, - std::vector transInd, std::vector rotInd, - const int levIndex, const int prtIndex) { +void ParticleMapper:: +add_mass_part_def(vector_type& vec,std::vector transInd, std::vector rotInd, + const int levIndex, const int prtIndex) +{ bool logGravity = false; - - if (logGravity) - UG_LOG( - "//////////////////////////////// - log momentum - ///////////////////////////////\n"); - if (logGravity) - UG_LOG("VORHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); - if (logGravity) - UG_LOG("VORHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); - if (logGravity) - UG_LOG("VORHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); if (logGravity) - UG_LOG("VORHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); - + { + UG_LOG("//////////////////////////////// - log momentum - ///////////////////////////////\n"); + UG_LOG("VORHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); + UG_LOG("VORHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); + UG_LOG("VORHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); + UG_LOG("VORHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); + } + number volume; - if (m_bVolumeCompExact) + if (m_bVolumeCompExact) // compute volume analytically volume = Volume(levIndex, prtIndex); - else + else // compute volume by adding volumes of elements, covered by the prtIndex-th particle volume = compute_volume(levIndex, prtIndex); const number mass = Mass(levIndex, prtIndex, volume); @@ -1607,90 +1204,94 @@ void ParticleMapper::add_mass_part_def(vector_type& vec, vScaleMass[0] = 1.0; vScaleMass[1] = -1.0; -// loop all time points and assemble them - for (int i = 1; i >= 0; --i) { +// loop all time points and add mass parts to global defect + for (int i = 1; i >= 0; --i) + { if (logGravity) UG_LOG("i = " << i << ":\n"); + for (int d = 0; d < dim; ++d) { - double transSol = m_spParticleHandlerGlobal->get_transSol(prtIndex, - i)[d]; - double rotSol = - m_spParticleHandlerGlobal->get_rotSol(prtIndex, i)[d]; - - if (logGravity) - UG_LOG("transSol(" << i << ") = " << transSol << "\n"); - if (logGravity) - UG_LOG("rotSol(" << i << ") = " << rotSol << "\n"); - - if (logGravity) - UG_LOG( - "+= vScaleMass[" << i << "]*mass*transSol = " << vScaleMass[i]*mass*transSol << "\n"); - if (logGravity) - UG_LOG( - "+= vScaleMass[" << i << "]*momOfInertia*rotSol = " << vScaleMass[i]*momOfInertia*rotSol << "\n"); - + double transSol = m_spCutElementHandler->get_transSol(prtIndex,i)[d]; + double rotSol = m_spCutElementHandler->get_rotSol(prtIndex, i)[d]; + DoFRef(vec, transInd[d]) += vScaleMass[i] * mass * transSol; if (dim == 3 || d == 0) DoFRef(vec, rotInd[d]) += vScaleMass[i] * momOfInertia * rotSol; + + if (logGravity) + { + UG_LOG("transSol(" << i << ") = " << transSol << "\n"); + UG_LOG("rotSol(" << i << ") = " << rotSol << "\n"); + UG_LOG("+= vScaleMass[" << i << "]*mass*transSol = " << vScaleMass[i]*mass*transSol << "\n"); + UG_LOG("+= vScaleMass[" << i << "]*momOfInertia*rotSol = " << vScaleMass[i]*momOfInertia*rotSol << "\n"); + } } } if (logGravity) + { UG_LOG("NACHHER: defect(trans,0): " << DoFRef(vec, transInd[0]) << "\n"); - if (logGravity) - UG_LOG( - "NACCHHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); - if (logGravity) - UG_LOG("NACHHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); - if (logGravity) - UG_LOG("NACHHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); + UG_LOG("NACCHHER: defect(trans,1): " << DoFRef(vec, transInd[1]) << "\n"); + UG_LOG("NACHHER: defect(rot,0): " << DoFRef(vec, rotInd[0]) << "\n"); + UG_LOG("NACHHER: defect(rot,1): " << DoFRef(vec, rotInd[1]) << "\n"); + } + +// call only ONCE!! (during 'modify_GlobalSol(): m_bFlagInertial := true) + if (m_bVolumeCompExact) + m_bFlagInertial[prtIndex] = false; -// during 'modify_GlobalSol(): m_bFlagInertial := true - if (m_bVolumeCompExact) - m_bFlagInertial[prtIndex] = false; // => call only ONCE + + return; } template -void ParticleMapper::add_rhs(vector_type& vec, - std::vector transInd, std::vector rotInd, - const int levIndex, const int prtIndex) { - - if (m_bFlagGravity[prtIndex]) +void ParticleMapper:: +add_rhs(vector_type& vec, std::vector transInd, std::vector rotInd, + const int levIndex, const int prtIndex) +{ + +// call assembling of gravitational force acting on prtIndex-th particle + if (m_bFlagGravity[prtIndex]){ set_gravitational_rhs(vec, transInd, rotInd, levIndex, prtIndex); + } +// call assembling of repuslive force acting on prtIndex-th particle if (m_bRepulsiveForce){ add_repulsive_force_rhs(vec, transInd, rotInd, levIndex, prtIndex); } +// call assembling of glowinski repuslive force acting on prtIndex-th particle if (m_bGlowRepulsiveForce){ add_glowinski_repulsive_force_rhs(vec, transInd, rotInd, levIndex, prtIndex); } - // no if here because of calculations and a UG_LOG call inside the function that should be printed everytime. - // if clause is inside the function and force is added only if m_bMaxRepulsiveForce +// no if here because of calculations and a UG_LOG call inside the function that should be printed everytime. +// if clause is inside the function and force is added only if m_bMaxRepulsiveForce add_minimum_correction_force_rhs(vec, transInd, rotInd, levIndex, prtIndex); -// during 'modify_GlobalSol(): m_bFlagGravity := true - if (m_bVolumeCompExact) - m_bFlagGravity[prtIndex] = false; // => call only ONCE +// call this method only ONCE!! (during 'modify_GlobalSol(): m_bFlagGravity := true) + if (m_bVolumeCompExact) + m_bFlagGravity[prtIndex] = false; } // call for 'CUT_BY_2_INTERFACE' template -void ParticleMapper::add_local_vec_to_global_interface_for2( - vector_type& vec, const LocalVector& lvec, - ConstSmartPtr dd) { - UG_LOG("start add_local_vec_to_global_interface_for2()\n"); +void ParticleMapper:: +add_local_vec_to_global_interface_for2(vector_type& vec, const LocalVector& lvec, + ConstSmartPtr dd) +{ + +// REMARK: not finally tested! + UG_THROW("ParticleMapper::add_local_vec_to_global_interface_for2(): not finally tested!!!!\n"); + // get data const int levIndex = get_Index(dd->grid_level(), dd); std::vector < DoFIndex > transInd1, rotInd1, transInd2, rotInd2; - m_spParticleHandlerGlobal->get_global_indices(transInd1, rotInd1, levIndex, - 0); - m_spParticleHandlerGlobal->get_global_indices(transInd2, rotInd2, levIndex, - 1); + m_spCutElementHandler->get_global_indices(transInd1, rotInd1, levIndex,0); + m_spCutElementHandler->get_global_indices(transInd2, rotInd2, levIndex,1); // A. add local to global if (!UsualAss()) @@ -1701,29 +1302,31 @@ void ParticleMapper::add_local_vec_to_global_interface_for2( add_local_vec_to_global_FT_for2(vec, lvec, transInd1, rotInd1, transInd2, rotInd2); else - UG_THROW( - "add_local_vec_to_global_interface_for2(): -> not implemented!\n"); + UG_THROW("add_local_vec_to_global_interface_for2(): -> not implemented!\n"); } // call for 'CUT_BY_INTERFACE' template -void ParticleMapper::add_local_vec_to_global_interface( - vector_type& vec, const LocalVector& lvec, - ConstSmartPtr dd) { +void ParticleMapper:: +add_local_vec_to_global_interface(vector_type& vec, const LocalVector& lvec, + ConstSmartPtr dd) +{ // get data const int levIndex = get_Index(dd->grid_level(), dd); const int prtIndex = get_prtIndex(); std::vector < DoFIndex > transInd, rotInd; - m_spParticleHandlerGlobal->get_global_indices(transInd, rotInd, levIndex, + m_spCutElementHandler->get_global_indices(transInd, rotInd, levIndex, prtIndex); // A. add local to global - if (!UsualAss()) + if (!UsualAss()){ add_local_vec_to_global_FT(vec, lvec, transInd, rotInd); - // else - // ToDo add_local_vec_to_global_usual(vec, lvec, dd); - + } + else { + UG_THROW("in ParticleMapper::add_local_vec_to_global_interface(): !UsualAss() not implemented!\n"); + } + // B. add mass part to defect if (m_bFlagInertial[prtIndex]) add_mass_part_def(vec, transInd, rotInd, levIndex, prtIndex); @@ -1734,89 +1337,13 @@ void ParticleMapper::add_local_vec_to_global_interface( } -/* - template - void ParticleMapper:: - add_local_mat_to_global_FT_for2(matrix_type& mat, const LocalMatrix& lmat, - std::vector transInd1, std::vector rotInd1, - std::vector transInd2, std::vector rotInd2) - { - UG_LOG("start add_local_mat_to_global_FT_for2()\n"); - - UG_LOG("transInd1: " << transInd1[0] << "\n"); - UG_LOG("transInd2: " << transInd2[0] << "\n"); - UG_LOG("rotInd1: " << rotInd1[0] << "\n"); - UG_LOG("rotInd2: " << rotInd2[0] << "\n"); - - MathMatrix rotationMatCo, rotationMatIP, rotationMatIP_transposed; - std::vector transInd_from, rotInd_from; - std::vector transInd_to, rotInd_to; - - UG_LOG("lmat.num_all_row_dof(0) = \n" << lmat.num_all_row_dof(0) << "\n"); - UG_LOG("lmat.num_all_row_dof(1) = \n" << lmat.num_all_row_dof(1) << "\n"); - if ( lmat.num_all_row_dof(0) != 4 ) - UG_THROW("lmat.num_all_row_dof(2) = \n" << lmat.num_all_row_dof(2) << "\n"); - - for(size_t fct1=0; fct1 < 2; ++fct1) - for(size_t fct2=0; fct2 < 2; ++fct2) - for(size_t dof1=0; dof1 < 4; ++dof1) - for(size_t dof2=0; dof2 < 4; ++dof2) - { - rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_co(dof2)); - rotationMatIP = m_spParticleHandlerGlobal->get_rotationMat(m_spInterfaceHandlerLocal->radial_at_ip(dof1)); - - UG_LOG("dof1: " << dof1 << ", m_spInterfaceHandlerLocal->radial_at_ip(dof1): " << m_spInterfaceHandlerLocal->radial_at_ip(dof1) << "\n"); - UG_LOG("dof2: " << dof2 << ", m_spInterfaceHandlerLocal->radial_at_co(dof2): " << m_spInterfaceHandlerLocal->radial_at_co(dof2) << "\n"); - - - // coupling FROM particle1 - if ( dof1 < 2 ) { transInd_from = transInd1; rotInd_from = rotInd1; } - // coupling FROM particle2 - else { transInd_from = transInd2; rotInd_from = rotInd2; } - // coupling TO particle1 - if ( dof2 < 2 ) { transInd_to = transInd1; rotInd_to = rotInd1; } - // coupling TO particle2 - else { transInd_to = transInd2; rotInd_to = rotInd2; } - - UG_LOG("transInd_from: " << transInd_from[0] << "\n"); - UG_LOG("rotInd_from: " << rotInd_from[0] << "\n"); - UG_LOG("transInd_to: " << transInd_to[0] << "\n"); - UG_LOG("rotInd_to: " << rotInd_to[0] << "\n"); - - UG_THROW("check it out...\n"); - - // trans-trans - DoFRef(mat, transInd_from[fct1], transInd_to[fct2]) - += lmat.value(fct1,dof1,fct2,dof2); - - // trans-rot - for ( size_t cmp = 0; cmp < dim; ++cmp ) - DoFRef(mat, transInd_from[fct1], rotInd_to[cmp]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp]; - - // rot-trans - for ( size_t cmp = 0; cmp < dim; ++cmp ) - DoFRef(mat, rotInd_from[cmp], transInd_to[fct2]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatIP[fct1][cmp]; - - // rot-rot - for ( size_t cmp1 = 0; cmp1 < dim; ++cmp1 ) - for ( size_t cmp2 = 0; cmp2 < dim; ++cmp2 ) - DoFRef(mat, rotInd_from[cmp1], rotInd_to[cmp2]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMatCo[fct2][cmp2]*rotationMatIP[fct1][cmp1]; - - } // end dof2-loop - - - - const LocalIndices& rowInd = lmat.get_row_indices(); - const LocalIndices& colInd = lmat.get_col_indices(); - - } - */ template -size_t ParticleMapper::map_for2(size_t dof) { +size_t ParticleMapper:: +map_for2(size_t dof) +{ + UG_THROW("ParticleMapper::map_for2(): not finally tested!\n"); + if (dof == 4) return m_spInterfaceHandlerLocal->m_vNOInterfaceID[0]; else if (dof < 2) @@ -1824,17 +1351,20 @@ size_t ParticleMapper::map_for2(size_t dof) { else if (dof >= 2) return m_spInterfaceHandlerLocal->m_vQuadriOrigID[dof]; else - UG_THROW( - "ParticleMapper::map_for2(): error: dof = " << dof << " should lie between 0 and 4!\n"); + UG_THROW("ParticleMapper::map_for2(): error: dof = " + << dof << " should lie between 0 and 4!\n"); } template -void ParticleMapper::add_local_mat_to_global_FT_for2_StdFV( +void ParticleMapper:: +add_local_mat_to_global_FT_for2_StdFV( matrix_type& mat, const LocalMatrix& lmat, std::vector transInd1, std::vector rotInd1, - std::vector transInd2, std::vector rotInd2) { - UG_LOG("----- START add_local_mat_to_global_FT_for2_StdFV()\n"); + std::vector transInd2, std::vector rotInd2) +{ +// REMARK: not finally tested! + UG_THROW("ParticleMapper::add_local_mat_to_global_FT_for2_StdFV(): not finally tested!!!!\n"); MathMatrix rotationMatCo, rotationMatIP, rotationMatIP_transposed; MathVector radialVector; @@ -1852,18 +1382,6 @@ void ParticleMapper::add_local_mat_to_global_FT_for2_StdFV( const DoFIndex indexRow = DoFIndex(rowInd.index(fct1, _dof1), rowInd.comp(fct1, _dof1)); - UG_LOG("fct1 " << fct1 << "_dof1 " << _dof1 << "\n"); - - if (indexRow[0] == 15) { - UG_LOG( - "rowInd.index(fct1,_dof1) = " << rowInd.index(fct1,_dof1) << "\n"); - } else { - UG_LOG("indexRow[0] = " << indexRow[0] << "\n"); - } - - if (indexRow[0] == 1 && dof1 != 2) - UG_THROW("aha...dof1 = " << dof1 << "\n"); - for (size_t fct2 = 0; fct2 < lmat.num_all_col_fct(); ++fct2) for (size_t dof2 = 0; dof2 < lmat.num_all_col_dof(fct2); ++dof2) { @@ -1874,14 +1392,12 @@ void ParticleMapper::add_local_mat_to_global_FT_for2_StdFV( colInd.index(fct2, _dof2), colInd.comp(fct2, _dof2)); - if (indexRow[0] == 15 && indexCol[0] == 17) - UG_LOG("cut by 2??\n"); size_t modus = getMappingModus(fct1, _dof1, fct2, _dof2); - rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat( + rotationMatCo = m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_co(dof2)); - rotationMatIP = m_spParticleHandlerGlobal->get_rotationMat( + rotationMatIP = m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_ip(dof1)); const int prtIndex1 = getPrtIndex(_dof1); @@ -1895,12 +1411,12 @@ void ParticleMapper::add_local_mat_to_global_FT_for2_StdFV( break; case 1: { std::vector < DoFIndex > transInd_to, rotInd_to; - // coupling TO particle1 + // coupling TO particle1 if (prtIndex2 == 0) { transInd_to = transInd1; rotInd_to = rotInd1; - } - // coupling TO particle2 + } + // coupling TO particle2 else { transInd_to = transInd2; rotInd_to = rotInd2; @@ -1918,12 +1434,12 @@ void ParticleMapper::add_local_mat_to_global_FT_for2_StdFV( break; case 2: { std::vector < DoFIndex > transInd_from, rotInd_from; - // coupling FROM particle1 + // coupling FROM particle1 if (prtIndex1 == 0) { transInd_from = transInd1; rotInd_from = rotInd1; } - // coupling FROM particle2 + // coupling FROM particle2 else { transInd_from = transInd2; rotInd_from = rotInd2; @@ -1942,33 +1458,33 @@ void ParticleMapper::add_local_mat_to_global_FT_for2_StdFV( case 3: { std::vector < DoFIndex > transInd_from, rotInd_from; std::vector < DoFIndex > transInd_to, rotInd_to; - // coupling TO particle1 + // coupling TO particle1 if (prtIndex2 == 0) { transInd_to = transInd1; rotInd_to = rotInd1; } - // coupling TO particle2 + // coupling TO particle2 else { transInd_to = transInd2; rotInd_to = rotInd2; } - // coupling FROM particle1 + // coupling FROM particle1 if (prtIndex1 == 0) { transInd_from = transInd1; rotInd_from = rotInd1; } - // coupling FROM particle2 + // coupling FROM particle2 else { transInd_from = transInd2; rotInd_from = rotInd2; } - // trans-trans + // trans-trans DoFRef(mat, transInd_from[fct1], transInd_to[fct2]) += lmat.value(fct1, dof1, fct2, dof2); - // trans-rot ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) + // trans-rot ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) for (size_t cmp = 0; cmp < dim; ++cmp) DoFRef(mat, transInd_from[fct1], rotInd_to[cmp]) += lmat.value(fct1, dof1, fct2, dof2) @@ -1996,20 +1512,21 @@ void ParticleMapper::add_local_mat_to_global_FT_for2_StdFV( throw(UGError("Error in LocToGlob!")); } // end switch-cases - } // end dof2-loop } - UG_LOG("----- END add_local_mat_to_global_FT_for2_StdFV()\n"); } template -void ParticleMapper::add_local_mat_to_global_FT_for2( +void ParticleMapper:: +add_local_mat_to_global_FT_for2( matrix_type& mat, const LocalMatrix& lmat, std::vector transInd1, std::vector rotInd1, - std::vector transInd2, std::vector rotInd2) { - UG_LOG("--- START add_local_mat_to_global_FT_for2()\n"); + std::vector transInd2, std::vector rotInd2) +{ +// REMARK: not finally tested! + UG_THROW("ParticleMapper::add_local_mat_to_global_FT_for2(): not finally tested!!!!\n"); MathMatrix rotationMatCo, rotationMatIP, rotationMatIP_transposed; MathVector radialVector; @@ -2031,19 +1548,11 @@ void ParticleMapper::add_local_mat_to_global_FT_for2( colInd.index(fct2, dofMap2), colInd.comp(fct2, dofMap2)); - UG_LOG("dof1: " << dof1 << ", dofMap1: " << dofMap1 << "\n"); - UG_LOG("dof2: " << dof2 << ", dofMap2: " << dofMap2 << "\n"); - - rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat( + rotationMatCo = m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_co(dof2)); - rotationMatIP = m_spParticleHandlerGlobal->get_rotationMat( + rotationMatIP = m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_ip(dof1)); - - UG_LOG( - "dof1: " << dof1 << ", m_spInterfaceHandlerLocal->radial_at_ip(dof1): " << m_spInterfaceHandlerLocal->radial_at_ip(dof1) << "\n"); - UG_LOG( - "dof2: " << dof2 << ", m_spInterfaceHandlerLocal->radial_at_co(dof2): " << m_spInterfaceHandlerLocal->radial_at_co(dof2) << "\n"); - + size_t modus = getMappingModus_for2(fct1, dof1, fct2, dof2); switch (modus) { @@ -2054,19 +1563,17 @@ void ParticleMapper::add_local_mat_to_global_FT_for2( break; case 1: { std::vector < DoFIndex > transInd_to, rotInd_to; - // coupling TO particle1 + // coupling TO particle1 if (dof2 < 2) { transInd_to = transInd1; rotInd_to = rotInd1; } - // coupling TO particle2 + // coupling TO particle2 else { transInd_to = transInd2; rotInd_to = rotInd2; } - UG_LOG("transInd_to: " << transInd_to[0] << "\n"); - UG_LOG("rotInd_to: " << rotInd_to[0] << "\n"); - + DoFRef(mat, indexRow, transInd_to[fct2]) += lmat.value( fct1, dof1, fct2, dof2); @@ -2079,12 +1586,12 @@ void ParticleMapper::add_local_mat_to_global_FT_for2( break; case 2: { std::vector < DoFIndex > transInd_from, rotInd_from; - // coupling FROM particle1 + // coupling FROM particle1 if (dof1 < 2) { transInd_from = transInd1; rotInd_from = rotInd1; } - // coupling FROM particle2 + // coupling FROM particle2 else { transInd_from = transInd2; rotInd_from = rotInd2; @@ -2105,12 +1612,12 @@ void ParticleMapper::add_local_mat_to_global_FT_for2( case 3: { std::vector < DoFIndex > transInd_from, rotInd_from; std::vector < DoFIndex > transInd_to, rotInd_to; - // coupling TO particle1 + // coupling TO particle1 if (dof2 < 2) { transInd_to = transInd1; rotInd_to = rotInd1; } - // coupling TO particle2 + // coupling TO particle2 else { transInd_to = transInd2; rotInd_to = rotInd2; @@ -2118,12 +1625,12 @@ void ParticleMapper::add_local_mat_to_global_FT_for2( UG_LOG("transInd_to: " << transInd_to[0] << "\n"); UG_LOG("rotInd_to: " << rotInd_to[0] << "\n"); - // coupling FROM particle1 + // coupling FROM particle1 if (dof1 < 2) { transInd_from = transInd1; rotInd_from = rotInd1; } - // coupling FROM particle2 + // coupling FROM particle2 else { transInd_from = transInd2; rotInd_from = rotInd2; @@ -2131,11 +1638,11 @@ void ParticleMapper::add_local_mat_to_global_FT_for2( UG_LOG("transInd_from: " << transInd_from[0] << "\n"); UG_LOG("rotInd_from: " << rotInd_from[0] << "\n"); - // trans-trans + // trans-trans DoFRef(mat, transInd_from[fct1], transInd_to[fct2]) += lmat.value(fct1, dof1, fct2, dof2); - // trans-rot ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) + // trans-rot ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) for (size_t cmp = 0; cmp < dim; ++cmp) DoFRef(mat, transInd_from[fct1], rotInd_to[cmp]) += lmat.value(fct1, dof1, fct2, dof2) @@ -2188,26 +1695,23 @@ void ParticleMapper::add_local_mat_to_global_FT_for2( } } // end dof1-loop - if (0) // m_spInterfaceHandlerLocal->interface_id_all().size() == 2 ) - UG_THROW("check it out...\n"); - UG_LOG("--- END add_local_mat_to_global_FT_for2()\n"); } template -void ParticleMapper::add_local_mat_to_global_FT( - matrix_type& mat, const LocalMatrix& lmat, - std::vector transInd, std::vector rotInd) { +void ParticleMapper:: +add_local_mat_to_global_FT(matrix_type& mat, const LocalMatrix& lmat, + std::vector transInd, std::vector rotInd) +{ bool bOld = true; bool remap = true; - bool transposed = false; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // VORSICHT: lmat hat algebra-struktur und groesse von m_locJ, also potentiell groesser, wenn quadrilateral!! - // ABER: ENTHAELT an alten indices noch originale global-index-Info: - // lmat haelt sich eigenen LocalIndices-member: lmat.m_pRowIndex, lmat.m_pColIndex - // mit lmat.resize(ind) = lmat.resize(ind,ind) => lmat.m_pRowIndex = ind, lmat.m_pColIndex = ind - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ATTENTION: lmat has the algebra-structure and size of m_locJ (i.e. bigger than standard, in case of QUADIR) +// BUT: the indices-infos are still the original one for the associated global indices: +// --> lmat.m_pRowIndex, lmat.m_pColIndex +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// LocalMatrix locMatOrig = lmat; LocalMatrix locMatTrans = lmat; @@ -2221,13 +1725,6 @@ void ParticleMapper::add_local_mat_to_global_FT( // for LocToGLob-mapping only the following geo-data are needed: // geo.vOriginalCornerID, geo.vInterfaceID, geo.m_bUseOriginalCornerRadial, // geo.m_vRadialAtCo, geo.m_vRadialAtIP - // - // => no scfv-data, but radial info: - // This can be handled USING ONLY geo_IB: - // - case 1 => PrsGeom; case 2/3 => IBGeom; - // - case 1 => geo_Prs.m_vRadialAtCo == geo_IB.m_vRadialAtCo :-) - // - // => usage of ONLY geo_IB-data possible, since all needed data is identic wit geo_Prs:-) //////////////////////////////////////////////////////////////////////////////////////////////////// MathMatrix rotationMatCo, rotationMatIP; @@ -2240,8 +1737,7 @@ void ParticleMapper::add_local_mat_to_global_FT( const int prtIndex = get_prtIndex(); if (prtIndex == -1) - UG_THROW( - "ParticleMapper::add_local_mat_to_global_FT(): prtIndex invalid!: prtIndex = " << prtIndex << "\n"); + UG_THROW("ParticleMapper::add_local_mat_to_global_FT(): prtIndex invalid!: prtIndex = " << prtIndex << "\n"); for (size_t fct1 = 0; fct1 < lmat.num_all_row_fct(); ++fct1) for (size_t dof1 = 0; dof1 < lmat.num_all_row_dof(fct1); ++dof1) { @@ -2252,14 +1748,10 @@ void ParticleMapper::add_local_mat_to_global_FT( const DoFIndex indexRow = DoFIndex(rowInd.index(fct1, _dof1), rowInd.comp(fct1, _dof1)); - if (indexRow[0] == 0) { - UG_LOG( - "rowInd.index(fct1,_dof1) = " << rowInd.index(fct1,_dof1) << "\n"); - } - for (size_t fct2 = 0; fct2 < lmat.num_all_col_fct(); ++fct2) for (size_t dof2 = 0; dof2 < lmat.num_all_col_dof(fct2); - ++dof2) { + ++dof2) + { size_t _dof2 = dof2; if (remap) @@ -2268,27 +1760,29 @@ void ParticleMapper::add_local_mat_to_global_FT( colInd.index(fct2, _dof2), colInd.comp(fct2, _dof2)); - if (indexRow[0] == 15 && indexCol[0] == 17) - UG_LOG("cut by 2??\n"); - size_t modus = getMappingModus(fct1, _dof1, fct2, _dof2); - if (1) //ToDo? m_spInterfaceHandlerLocal->m_bUseOriginalCornerRadial ) + + //////////////////////////////////////////////////////////////////////////////////////////////////// + // compute according rotational matrices: + // --> the couplings to/from the angular velocity need to be multiplied by + // the matrix resutling from the cross product + if (1) //or: if ( m_spInterfaceHandlerLocal->m_bUseOriginalCornerRadial ) { rotationMatCo = - m_spParticleHandlerGlobal->get_rotationMat( + m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_co( dof2)); rotationMatIP = - m_spParticleHandlerGlobal->get_rotationMat( + m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_ip( dof1)); } else { rotationMatCo = - m_spParticleHandlerGlobal->get_rotationMat( + m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_co( dof2)); rotationMatIP = - m_spParticleHandlerGlobal->get_rotationMat( + m_spCutElementHandler->get_rotationMat( m_spInterfaceHandlerLocal->radial_at_ip( dof1)); } @@ -2296,49 +1790,43 @@ void ParticleMapper::add_local_mat_to_global_FT( MathMatrix rotationMatIP_transposed; Transpose(rotationMatIP_transposed, rotationMatIP); + //////////////////////////////////////////////////////////////////////////////////////////////////// + // for explanations on the mapping modus, see 'loc_to_glob_mapper_particle.h' switch (modus) { case 0: { - DoFRef(mat, indexRow, indexCol) += lmat.value(fct1, - dof1, fct2, dof2); + DoFRef(mat, indexRow, indexCol) += lmat.value(fct1, dof1, fct2, dof2); } break; case 1: { - DoFRef(mat, indexRow, transInd[fct2]) += lmat.value( - fct1, dof1, fct2, dof2); + DoFRef(mat, indexRow, transInd[fct2]) += lmat.value(fct1, dof1, fct2, dof2); for (size_t cmp = 0; cmp < dim; ++cmp) { - DoFRef(mat, indexRow, rotInd[cmp]) += lmat.value( - fct1, dof1, fct2, dof2) + DoFRef(mat, indexRow, rotInd[cmp]) += lmat.value(fct1, dof1, fct2, dof2) * rotationMatCo[fct2][cmp]; } } break; case 2: { - if (!m_spParticleHandlerGlobal->get_DoF_modus_linear( - prtIndex)) + if (!m_spCutElementHandler->get_DoF_modus_linear(prtIndex)) DoFRef(mat, transInd[fct1], indexCol) += lmat.value( - fct1, dof1, fct2, dof2); + fct1, dof1, fct2, dof2); - // NOT ONLY assemble particle->velFluid, even IF \int (r x p*n) = 0 - // fct2 == dim NOTWENDIG, da im Fall von irregulaeren Gittern der Defekt sonst inkonsistent werden KANN - // -> getestet mit 'ExactSol_FT.lua' und 'grids/unit_square_tri_irregular_2x2_4_Boundaries.ugx' + // assemble entries, EVEN THOUGH it is: \int (r x p*n) = 0 + // --> fct2 == dim NECESSARY, since in case of irregular meshes, the entries can get inconsistent! + // --> this effect was tested and observed for some numerical test simulations for (size_t cmp = 0; cmp < dim; ++cmp) { - //const DoFIndex tmp_indexCol = DoFIndex(colInd.index(cmp,_dof2), colInd.comp(cmp,_dof2)); if (transposed) { - if (!m_spParticleHandlerGlobal->get_DoF_modus_angular( - prtIndex)) + if (!m_spCutElementHandler->get_DoF_modus_angular(prtIndex)) DoFRef(mat, rotInd[cmp], indexCol) += lmat.value(fct1, dof1, fct2, dof2) * rotationMatIP[cmp][fct1]; } else { - if (1) //fct2 != dim ) + if (1) //or: if ( fct2 != dim ) { - if (!m_spParticleHandlerGlobal->get_DoF_modus_angular( - prtIndex)) + if (!m_spCutElementHandler->get_DoF_modus_angular(prtIndex)) DoFRef(mat, rotInd[cmp], indexCol) += - lmat.value(fct1, dof1, fct2, - dof2) + lmat.value(fct1, dof1, fct2,dof2) * rotationMatIP[fct1][cmp]; } } @@ -2349,22 +1837,21 @@ void ParticleMapper::add_local_mat_to_global_FT( break; case 3: { - if (!m_spParticleHandlerGlobal->get_DoF_modus_linear( - prtIndex)) { - - // trans-trans + if (!m_spCutElementHandler->get_DoF_modus_linear(prtIndex)) + { + // trans -> trans DoFRef(mat, transInd[fct1], transInd[fct2]) += lmat.value(fct1, dof1, fct2, dof2); - // trans-rot ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) + // trans -> rot: ( w x r = w x r_co = R_co^T*w); (R^T*... <=> [fct1][cmp]) for (size_t cmp = 0; cmp < dim; ++cmp) DoFRef(mat, transInd[fct1], rotInd[cmp]) += lmat.value(fct1, dof1, fct2, dof2) * rotationMatCo[fct2][cmp]; } - if (!m_spParticleHandlerGlobal->get_DoF_modus_angular( - prtIndex)) { + if (!m_spCutElementHandler->get_DoF_modus_angular(prtIndex)) + { if (bOld) { if (transposed) { for (size_t cmp = 0; cmp < dim; ++cmp) @@ -2380,15 +1867,7 @@ void ParticleMapper::add_local_mat_to_global_FT( * rotationMatIP[fct1][cmp]; } - // rot-rot ( r x (w x r) = r_ip x (w x r_co) = R_ip*R_co^T*w = (R_co*R_ip^T)^T*w) ; ) (...^T*w <=> [fct1][cmp]) - // ToDo: statt (R_co*R_ip^T)^T*w) und [fct1][cmp]: R_ip*R_co^T und [cmp][fct1] - //R^T * R = (r_1)^2 + (r_2)2 - /* number r1 = geo.m_vRadialAtIP[dof1][0]*geo.m_vRadialAtCo[dof2][0]; - number r2 = geo.m_vRadialAtIP[dof1][1]*geo.m_vRadialAtCo[dof2][1]; - number dist_IP = r1 + r2; - DoFRef(mat, rotInd[0], rotInd[0]) - += lmat.value(fct1,dof1,fct2,dof2)*dist_IP; - */ + // rot -> rot: ( r x (w x r) = r_ip x (w x r_co) = R_ip*R_co^T*w = (R_co*R_ip^T)^T*w) ; ) (...^T*w <=> [fct1][cmp]) if (transposed) { for (size_t cmp1 = 0; cmp1 < dim; ++cmp1) for (size_t cmp2 = 0; cmp2 < dim; @@ -2409,7 +1888,9 @@ void ParticleMapper::add_local_mat_to_global_FT( * rotationMatIP[fct1][cmp1]; } } else { - DoFRef(mat, rotInd[fct1], transInd[fct2]) += + // use local couplings computed by class 'ParticleBndCond' + // and add those to global matrix + DoFRef(mat, rotInd[fct1], transInd[fct2]) += get_rotJ_ind(fct1, dof1, fct2, dof2); DoFRef(mat, rotInd[fct1], rotInd[fct2]) += get_rotJ_rot(fct1, dof1, fct2, dof2); @@ -2448,7 +1929,7 @@ void ParticleMapper::add_local_mat_to_global_FT( } else //if transInd or rotInd lie on cut element and are given by the user, i.e. NO DoFs! { // set dirichlet row for translation vel - if (m_spParticleHandlerGlobal->get_DoF_modus_linear( + if (m_spCutElementHandler->get_DoF_modus_linear( prtIndex)) { for (size_t d = 0; d < dim; ++d) { const DoFIndex indexDiag = DoFIndex( @@ -2458,7 +1939,7 @@ void ParticleMapper::add_local_mat_to_global_FT( } } // set dirichlet row for rotation vel - if (m_spParticleHandlerGlobal->get_DoF_modus_angular( + if (m_spCutElementHandler->get_DoF_modus_angular( prtIndex)) { for (size_t d = 0; d < dim; ++d) { const DoFIndex indexDiag = DoFIndex( @@ -2474,15 +1955,19 @@ void ParticleMapper::add_local_mat_to_global_FT( } template -void ParticleMapper::assemble_QuadriCorners(vector_type& vec, +void ParticleMapper:: +assemble_QuadriCorners(vector_type& vec, const LocalVector& lvec, std::vector transInd1, std::vector rotInd1, std::vector transInd2, - std::vector rotInd2) { - return; + std::vector rotInd2) +{ +// REMARK: not finally tested! + return; + + if (dim == 3) UG_THROW("in 'assemble_QuadriCorners()': not implemented!\n"); - UG_LOG("\n start assemble_fluid_nodes()\n"); UG_LOG("transInd1: " << transInd1[0] << "transInd2: " << transInd2[0] << "\n"); UG_LOG("rotInd1: " << rotInd1[0] << "rotInd2: " << rotInd2[0] << "\n"); @@ -2514,25 +1999,20 @@ void ParticleMapper::assemble_QuadriCorners(vector_type& vec, } template -void ParticleMapper::assemble_fluid_nodes(vector_type& vec, - const LocalVector& lvec) { - UG_LOG("\n start assemble_fluid_nodes()\n"); - -} - -template -void ParticleMapper::add_local_vec_to_global_FT_for2_StdFV( +void ParticleMapper:: +add_local_vec_to_global_FT_for2_StdFV( vector_type& vec, const LocalVector& lvec, std::vector transInd1, std::vector rotInd1, - std::vector transInd2, std::vector rotInd2) { + std::vector transInd2, std::vector rotInd2) +{ +// REMARK: not finally tested! + UG_THROW("ParticleMapper::add_local_vec_to_global_FT_for2_StdFV(): not finally tested!!!!\n"); + if (dim == 3) - UG_THROW( - "add_local_vec_to_global_FT_for2_StdFV() not implemented for 3d!!!\n"); + UG_THROW("add_local_vec_to_global_FT_for2_StdFV() not implemented for 3d!!!\n"); bool remap = true; - UG_LOG("start add_local_vec_to_gloabal_FT_for2_StdFV()\n"); - const LocalIndices& ind = lvec.get_indices(); for (size_t fct = 0; fct < lvec.num_all_fct(); ++fct) @@ -2540,75 +2020,55 @@ void ParticleMapper::add_local_vec_to_global_FT_for2_StdFV( if (lvec.value(fct, dof) != lvec.value(fct, dof)) UG_THROW("NAN in 'add_local_vec_to_global_FT()'!...\n"); if (lvec.value(fct, dof) > 1e+10) - UG_THROW( - "-----------------------> 1e+10: " << lvec.value(fct,dof) << "\n"); + UG_THROW("-----------------------> 1e+10: " << lvec.value(fct,dof) << "\n"); size_t _dof = dof; if (remap) _dof = m_spInterfaceHandlerLocal->corner_orig(dof); - const DoFIndex multi_index = DoFIndex(ind.index(fct, _dof), - ind.comp(fct, _dof)); - - UG_LOG("dof: " << dof << ", _dof: " << _dof << "\n"); - UG_LOG("fct: " << fct << "\n"); - + const DoFIndex multi_index = DoFIndex(ind.index(fct, _dof),ind.comp(fct, _dof)); const int prtIndex = getPrtIndex(_dof); - UG_LOG("nach 'getPrtIndex(dof)': prtIndex = " << prtIndex << "\n"); - - bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface( - _dof); + bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(_dof); - // usual assembling for fluid-dof and pressure-fct + // usual assembling for fluid-dof and pressure-fct if (!isPrtNode || fct == dim) { DoFRef(vec, multi_index) += lvec.value(fct, dof); - UG_LOG( - "added for fct = " << fct << ", dof = " << dof << ": " << lvec.value(fct,dof) << "\n"); + UG_LOG("added for fct = " << fct << ", dof = " << dof << ": " << lvec.value(fct,dof) << "\n"); } else { MathVector RotVec; RotVec[0] = -m_spInterfaceHandlerLocal->radial_at_ip(dof)[1]; RotVec[1] = m_spInterfaceHandlerLocal->radial_at_ip(dof)[0]; - UG_LOG( - "dof: " << dof << ", m_spInterfaceHandlerLocal->radial_at_ip(dof): " << m_spInterfaceHandlerLocal->radial_at_ip(dof) << "\n"); - DoFIndex transInd, rotInd; if (prtIndex == 0) { transInd = transInd1[fct]; rotInd = rotInd1[0]; - UG_LOG( - "transInd1[" << fct << "] = " << transInd1[fct] << "\n"); - } else { + } else { if (prtIndex != 1) UG_THROW("prtIndex = " << prtIndex << "\n"); + transInd = transInd2[fct]; rotInd = rotInd2[0]; - UG_LOG( - "transInd2[" << fct << "] = " << transInd2[fct] << "\n"); } // finally add connection between the 2 particles: DoFRef(vec, transInd) += lvec.value(fct, dof); DoFRef(vec, rotInd) += lvec.value(fct, dof) * RotVec[fct]; - - UG_LOG( - "----> added for fct = " << fct << ", dof = " << dof << ": " << lvec.value(fct,dof) << "\n"); - UG_LOG("RotVec = " << RotVec[fct] << "\n"); } } - - UG_LOG("end add_local_vec_to_gloabal_FT_for2_StdFV()\n\n"); - } template -void ParticleMapper::add_local_vec_to_global_FT_for2( +void ParticleMapper:: +add_local_vec_to_global_FT_for2( vector_type& vec, const LocalVector& lvec, std::vector transInd1, std::vector rotInd1, - std::vector transInd2, std::vector rotInd2) { - UG_LOG("start add_local_vec_to_gloabal_FT_for2()\n"); + std::vector transInd2, std::vector rotInd2) +{ +// REMARK: not finally tested! + UG_THROW("ParticleMapper::add_local_vec_to_global_FT_for2(): not finally tested!!!!\n"); const LocalIndices& ind = lvec.get_indices(); @@ -2621,67 +2081,46 @@ void ParticleMapper::add_local_vec_to_global_FT_for2( const DoFIndex multi_index = DoFIndex(ind.index(fct, dofMap), ind.comp(fct, dofMap)); - UG_LOG("dof: " << dof << ", dofMap: " << dofMap << "\n"); - UG_LOG("fct: " << fct << "\n"); - - // usual assembling for fluid-dof and pressure-fct + // usual assembling for fluid-dof and pressure-fct if (dof == 4 || fct == dim) { DoFRef(vec, multi_index) += lvec.value(fct, dof); - UG_LOG( - "added for fct = " << fct << ", dof = " << dof << ": " << lvec.value(fct,dof) << "\n"); } else { MathVector RotVec; RotVec[0] = -m_spInterfaceHandlerLocal->radial_at_ip(dof)[1]; RotVec[1] = m_spInterfaceHandlerLocal->radial_at_ip(dof)[0]; - UG_LOG( - "dof: " << dof << ", m_spInterfaceHandlerLocal->radial_at_ip(dof): " << m_spInterfaceHandlerLocal->radial_at_ip(dof) << "\n"); - DoFIndex transInd, rotInd; if (dof < 2) { transInd = transInd1[fct]; rotInd = rotInd1[0]; - UG_LOG( - "transInd1[" << fct << "] = " << transInd1[fct] << "\n"); - } else { + } else { transInd = transInd2[fct]; rotInd = rotInd2[0]; - UG_LOG( - "transInd2[" << fct << "] = " << transInd2[fct] << "\n"); - } + } // finally add connection between the 2 particles: DoFRef(vec, transInd) += lvec.value(fct, dof); DoFRef(vec, rotInd) += lvec.value(fct, dof) * RotVec[fct]; - UG_LOG( - "----> added for fct = " << fct << ", dof = " << dof << ": " << lvec.value(fct,dof) << "\n"); - UG_LOG("RotVec = " << RotVec[fct] << "\n"); - } + } } - - if (1) //m_spInterfaceHandlerLocal->interface_id_all().size() == 4 ) - UG_LOG("end add_local_vec_to_gloabal_FT_for2()\n\n"); - } template -void ParticleMapper::add_local_vec_to_global_FT( - vector_type& vec, const LocalVector& lvec, +void ParticleMapper:: +add_local_vec_to_global_FT(vector_type& vec, const LocalVector& lvec, std::vector transInd, std::vector rotInd) { const LocalIndices& ind = lvec.get_indices(); - bool remap = true; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // VORSICHT: lmat hat algebra-struktur und groesse von m_locJ, also potentiell groesser, wenn quadrilateral!! - // ABER: ENTHAELT an alten indices noch originale global-index-Info: - // lmat haelt sich eigenen LocalIndices-member: lmat.m_pRowIndex, lmat.m_pColIndex - // mit lmat.resize(ind) = lmat.resize(ind,ind) => lmat.m_pRowIndex = ind, lmat.m_pColIndex = ind - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ATTENTION: lmat has the algebra-structure and size of m_locJ (i.e. bigger than standard, in case of QUADIR) +// BUT: the indices-infos are still the original one for the associated global indices: +// --> lmat.m_pRowIndex, lmat.m_pColIndex +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// LocalVector locMatOrig = lvec; LocalVector locMatTrans = lvec; @@ -2692,30 +2131,31 @@ void ParticleMapper::add_local_vec_to_global_FT( const int prtIndex = get_prtIndex(); if (prtIndex == -1) - UG_THROW( - "ParticleMapper::add_local_mat_to_global_FT(): prtIndex invalid!: prtIndex = " << prtIndex << "\n"); + UG_THROW("ParticleMapper::add_local_mat_to_global_FT(): prtIndex invalid!: prtIndex = " + << prtIndex << "\n"); for (size_t fct = 0; fct < lvec.num_all_fct(); ++fct) { for (size_t dof = 0; dof < lvec.num_all_dof(fct); ++dof) { + + // some security checks: if (lvec.value(fct, dof) != lvec.value(fct, dof)) UG_THROW("NAN in 'add_local_vec_to_global_FT()'!...\n"); if (lvec.value(fct, dof) > 1e+10) UG_THROW("-----------------------> 1e+10: " << lvec.value(fct,dof) << "\n"); + // if remapping is done, the solution space turns into the 'flat top' shape, since ALL + // DoFs on the interface get associated (mapped) onto the original vertex of the mesh size_t _dof = dof; if (remap) _dof = m_spInterfaceHandlerLocal->corner_orig(dof); const DoFIndex multi_index = DoFIndex(ind.index(fct, _dof), ind.comp(fct, _dof)); -// const DoFIndex _multi_index = DoFIndex(ind.index(fct, dof), -// ind.comp(fct, dof)); - bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface( - _dof); + bool isPrtNode = m_spInterfaceHandlerLocal->remapped_fromInterface(_dof); - // usual assembling for fluid-dof and pressure-fct + // usual assembling for fluid-dof OR pressure-fct (continuity equation) if (!isPrtNode || fct == dim) { DoFRef(vec, multi_index) += lvec.value(fct, dof); } @@ -2724,26 +2164,27 @@ void ParticleMapper::add_local_vec_to_global_FT( // do nothing... } else { - if (!m_spParticleHandlerGlobal->get_DoF_modus_linear(prtIndex)) + // check, if the linear velocity is given by the user: => NO need to be assembled + if (!m_spCutElementHandler->get_DoF_modus_linear(prtIndex)) DoFRef(vec, transInd[fct]) += lvec.value(fct, dof); - - if (!m_spParticleHandlerGlobal->get_DoF_modus_angular( - prtIndex)) { + + // check, if the angular velocity is given by the user: => NO need to be assembled + if (!m_spCutElementHandler->get_DoF_modus_angular(prtIndex)) + { + //////////////////////////////////////////////////////////////////////////////////////////////////// + // for the entries of the angular velocity, they need to be multiplied by + // the matrix resutling from the cross product MathVector RotVec; if (dim == 2) { - RotVec[0] = -m_spInterfaceHandlerLocal->radial_at_ip( - dof)[1]; - RotVec[1] = - m_spInterfaceHandlerLocal->radial_at_ip(dof)[0]; + RotVec[0] = -m_spInterfaceHandlerLocal->radial_at_ip(dof)[1]; + RotVec[1] = m_spInterfaceHandlerLocal->radial_at_ip(dof)[0]; } MathMatrix rotationMatCo, rotationMatIP; MathMatrix rotationMatIP_transposed; if (dim == 3) { - rotationMatIP = - m_spParticleHandlerGlobal->get_rotationMat( - m_spInterfaceHandlerLocal->radial_at_ip( - dof)); + rotationMatIP = m_spCutElementHandler->get_rotationMat( + m_spInterfaceHandlerLocal->radial_at_ip(dof)); Transpose(rotationMatIP_transposed, rotationMatIP); } MathVector Pos; @@ -2751,14 +2192,12 @@ void ParticleMapper::add_local_vec_to_global_FT( Pos[1] = m_spInterfaceHandlerLocal->radial_at_ip(dof)[1]; if (dim == 2) - DoFRef(vec, rotInd[0]) += lvec.value(fct, dof) - * RotVec[fct]; - // DoFRef(vec, rotInd[0]) += sqrt(lvec.value(fct,dof)*RotVec[fct]*lvec.value(fct,dof)*RotVec[fct]); + DoFRef(vec, rotInd[0]) += lvec.value(fct, dof) * RotVec[fct]; if (dim == 3) - for (size_t cmp = 0; cmp < dim; ++cmp) DoFRef(vec, rotInd[cmp]) += lvec.value(fct, dof) * rotationMatIP_transposed[cmp][fct]; + } // end if (...DoF_modus_angular() ) } diff --git a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_tools.h b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_tools.h deleted file mode 100644 index 048998c..0000000 --- a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_tools.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - * moving_particle_tools.h - * - * Created on: 20.01.2015 - * Author: suze - */ - -#ifndef PARTICLE_MAPPER_TOOLS_H_ -#define PARTICLE_MAPPER_TOOLS_H_ - -namespace ug{ -namespace NavierStokes{ - -/* -template -void ParticleMapper:: -add_local_mat_to_global_usual(matrix_type& mat, const LocalMatrix& lmat, ConstSmartPtr dd) -{ -// get level index for 'isFluidDoF()' - level dependent! - const int Index = m_myParticle->get_Index(dd->grid_level()); - - PROFILE_FUNC(); - - - const LocalIndices& rowInd = lmat.get_row_indices(); - const LocalIndices& colInd = lmat.get_col_indices(); - - - // index of particle, the element is associated to - int prtIndex, prtIndex_ref = -1; - size_t indexList1; // indexList1 = entry in 'm_vvvIndexRadialPair_List', see 'is_marked()' - // indexList2 = entry in 'm_vvvIndexPosPair_List2', see 'is_borderFluid()' - - bool cutElem = false; - cutElem = elemIsCut(rowInd, lmat.num_all_row_dof(0), Index, &prtIndex, dd); - - for(size_t fct1=0; fct1 < lmat.num_all_row_fct(); ++fct1) - { - // scv-loop: - for(size_t dof1=0; dof1 < lmat.num_all_row_dof(fct1); ++dof1) - { - - const size_t rowIndex = rowInd.index(fct1,dof1); - const size_t rowComp = rowInd.comp(fct1,dof1); - - DoFIndex multi_index_row = DoFIndex(rowIndex, rowComp); - - // if the corresponding DoF is 'inside the fluid' OR 'pressure-DoF': - /////////////////////////////////////////////////////////// - // REMARK: - // if m_bExtrapolatePrs = true: - // is_marked() = true also for pressure-DoFs inside the particle!! - // -> see: particle_tools.h: if ( m_dExtrapolatePrs ) ... - /////////////////////////////////////////////////////////// - if ( !is_marked(multi_index_row, Index, &prtIndex, &indexList1) ) - { - - for(size_t fct2=0; fct2 < lmat.num_all_col_fct(); ++fct2) - for(size_t dof2=0; dof2 < lmat.num_all_col_dof(fct2); ++dof2) - { - const size_t colIndex = colInd.index(fct2,dof2); - const size_t colComp = colInd.comp(fct2,dof2); - - DoFIndex multi_index_col = DoFIndex(colIndex, colComp); - - // if the target DoF is 'inside the fluid' OR 'pressure-DoF': do usual assembling... - /////////////////////////////////////////////////////////// - // REMARK: - // if m_bExtrapolatePrs = true: - // is_marked() = true also for pressure-DoFs inside the particle!! - // -> see: particle_tools.h: if ( m_dExtrapolatePrs ) ... - /////////////////////////////////////////////////////////// - if ( !is_marked(multi_index_col, Index, &prtIndex, &indexList1) ) - { - DoFRef(mat, multi_index_row, multi_index_col) - += lmat.value(fct1,dof1,fct2,dof2); - } - // if the target DoF is a velocity DoF in the particle: RECONNECT to Trans/Rot - else - { - // CHECK for elements, cut by two different particles: - if ( prtIndex_ref == -1 ) - prtIndex_ref = prtIndex; - - // get indices for re-Association: - DoFIndex transInd = m_myParticle->get_transInd_Comp(Index, prtIndex, fct2); - if ( !m_myParticle->m_bExtrapolate && (int)fct2 != dim ) - { - // CONNECT to Trans: - DoFRef(mat, multi_index_row, transInd) - += lmat.value(fct1,dof1,fct2,dof2); - - //UG_THROW("lmat.value(fct1,dof1,fct2,dof2) =" << lmat.value(fct1,dof1,fct2,dof2) << "\n"); - - // CONNECT to Rot: - if ( 1 ) {//fct1 != dim ){ - MathMatrix rotationMat; - get_rotationMat(multi_index_col, Index, prtIndex, rotationMat); - std::vector rotInd_ = m_myParticle->get_rotInd(Index, prtIndex); - for ( int cmp = 0; cmp < dim; ++cmp ) - DoFRef(mat, multi_index_row, rotInd_[cmp]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMat[fct2][cmp]; - } - } - else if ( (!m_myParticle->m_bExtrapolatePrs && (int)fct2 == dim) ) //( m_myParticle->m_ExtrapolationPrsMethod == 6 && (int)fct2 == dim) || - { - // do usual assembling for pressure DoF inside particle: - DoFRef(mat, multi_index_row, multi_index_col) - += lmat.value(fct1,dof1,fct2,dof2); - } - else if ( m_myParticle->m_bExtrapolatePrs && (int)fct1 == dim && (int)fct2 != dim ) - { - UG_THROW("Haehhh...dieser fall sollte schon abgedeckt sein?...:(...\n"); - if ( (int)fct2 != dim ) - { - // fct2 != dim => die standart coeffs fuer u\cdot n uebernehmen: - // CONNECT to Trans: - DoFRef(mat, multi_index_row, transInd) - += lmat.value(fct1,dof1,fct2,dof2); - - // CONNECT to Rot: - MathMatrix rotationMat; - get_rotationMat(multi_index_col, Index, prtIndex, rotationMat); - std::vector rotInd_ = m_myParticle->get_rotInd(Index, prtIndex); - for ( int cmp = 0; cmp < dim; ++cmp ) - DoFRef(mat, multi_index_row, rotInd_[cmp]) - += lmat.value(fct1,dof1,fct2,dof2)*rotationMat[fct2][cmp]; - } - - } - else //if ( (int) fct1 != dim && (int) fct2 == dim ) // druck beitraege aus ContEq (also fuer stab) werden einfach weggelassen! - { - - ////////////////////////////////////////////////////////////////////////// - // EXTRAPOLATION-AKTION - // - // 'isBorder' and 'coefficients' are computed depending on the - // chosen 'm_ExtrapolationMethod' - ////////////////////////////////////////////////////////////////////////// - // for ( size_t f = 0; f < lmat.num_all_row_dof(0); ++f ) - // UG_LOG("ind(" << f << ") = " << rowInd.index(0,f) << "\n"); - - std::vector ind; - for ( size_t f = 0; f < lmat.num_all_row_dof(0); ++f ) - ind.push_back(rowInd.index(0,f)); - - bool isBorder = false; // -> only substitute velocity-DoFs - vVertexExtrapolData coefficients; - size_t coeffComp; - - ////////////////////////////////////////////////////////////////////////// - // 'isBorder' and 'coefficients' - ////////////////////////////////////////////////////////////////////////// - if ( (int)fct2 != dim ) - { - if ( !m_myParticle->m_bExtrapolate ) - {UG_THROW("Mince!....case wrong handeled!....: IFF extrapolation of VELOCITY is NOT set, this case may not occur!\n");} - - coeffComp = colComp; - isBorder = m_myParticle->m_myExtrapolation->getCoefficients_byDoFIndex(&coefficients, multi_index_col, ind, Index, prtIndex); - } - else - { - if ( !m_myParticle->m_bExtrapolatePrs ) - {UG_THROW("Mince!....case wrong handeled!....: IFF extrapolation of PRESSURE is NOT set, this case may not occur!\n");} - - // re-set 'colComp', since in coefficients[] for pressure-extrapolation - // only 1 connection is stored! - coeffComp = 0; - isBorder = m_myParticle->m_myExtrapolationPrs->getCoefficients_byDoFIndex(&coefficients, multi_index_col, ind, Index, prtIndex); - - } - - ////////////////////////////////////////////////////////////////////////// - // final assembling with coefficient-weighting - // identically for BOTH extrapolationMethods!! - ////////////////////////////////////////////////////////////////////////// - if ( isBorder ) - { - - /// wird fuer Aufruf von 'projectDefect()' in 'particle_constraint_impl.h': - // std::pair indexPair = std::make_pair(multi_index_row, multi_index_col); - - // if ( m_myParticle->m_bExtrapolatePrs && (int)fct2 == dim ) - // m_myParticle->m_myExtrapolationPrs->set_locJData(lmat.value(fct1,dof1,fct2,dof2), indexPair, coefficients, Index, prtIndex); - - if ( multi_index_row[0] == 1783 ){ - UG_LOG("_____________ multi_index_row: " << multi_index_row << "\n"); - - UG_LOG("_____________ coeff.size(): " << coefficients[0].size() << "\n"); - UG_LOG("_____________ lmat.value(): " << lmat.value(fct1,dof1,fct2,dof2) << "\n"); - } - // write new entries coming from extrapolating equation for outVrt: - for ( size_t i = 0; i < coefficients[0].size(); ++i ) - { - - const size_t writeIndex = coefficients[coeffComp][i].second[0]; - const size_t writeComp = coefficients[coeffComp][i].second[1]; - const number lambda = coefficients[coeffComp][i].first; - DoFIndex writeInd = DoFIndex(writeIndex, writeComp); - - - //UG_LOG("ind_row: " << multi_index_row << "Ind_col: " << writeInd << "\n"); - //UG_LOG("lambda: " << lambda << "\n"); - - DoFRef(mat, multi_index_row, writeInd) - += lmat.value(fct1,dof1,fct2,dof2)*lambda; - } - //UG_LOG("_____\n"); - - } // end 'm_myParticle->m_bExtrapolate ' - - - } // else ( m_bExtrapolate = true ) - } - } // end dof2_loop - - - } // end !is_marked() - - - } // end dof1-loop - } // end fct1-loop - -} - -template -void ParticleMapper:: -add_local_vec_to_global_usual(vector_type& vec, const LocalVector& lvec, ConstSmartPtr dd) -{ - -// get level index for 'isFluidDoF()' - level dependent! - const int Index = m_myParticle->get_Index(dd->grid_level()); - - const LocalIndices& ind = lvec.get_indices(); - - // index of particle, the element is associated to - int prtIndex, prtIndex_ref = -1; - size_t indexList1 = 1013; - - bool cutElem = false; - if (1 ) // m_myParticle->m_bExtrapolatePrs ) - { -// bool skipAssemblingForOutsideElem; -// cutElem = elemIsCut(ind, lvec.num_all_dof(0), skipAssemblingForOutsideElem, Index, &prtIndex); - cutElem = elemIsCut(ind, lvec.num_all_dof(0), Index, &prtIndex, dd); - - if ( 0 ) //!cutElem ) - if ( skipAssemblingForOutsideElem ) - return; - } - - - - for(size_t fct=0; fct < lvec.num_all_fct(); ++fct) - { - // skip assembling of ContEy on cutElem in order to discretize the pure - // mass flux usind u \dot n via 'add_PureMassFlux' in 'particle_constraint_imol.h' - if ( m_myParticle->m_bExtrapolatePrs ) - if ( m_myParticle->m_myExtrapolationPrs->computePureMassFlux() && cutElem && (int)fct == dim ) - continue; - - for(size_t dof=0; dof < lvec.num_all_dof(fct); ++dof) - { - const size_t VecIndex = ind.index(fct,dof); - const size_t VecComp = ind.comp(fct,dof); - - DoFIndex multi_index = DoFIndex(VecIndex, VecComp); - - // if the corresponding DoF is 'inside the fluid' OR 'pressure-DoF': - if ( !is_marked(multi_index, Index, &prtIndex, &indexList1) ) - { - - // throw error, if defect has value 'nan': - if ( lvec.value(fct,dof) != lvec.value(fct,dof)) - { - UG_LOG("multiindex: " << multi_index << "\t" << indexList1 << "\n"); - UG_THROW("ParticleMap:add_local_vec_to_global: Matrix entry with error: lvec.value(fct,dof) = " << lvec.value(fct,dof) << "\n"); - } - - DoFRef(vec, multi_index) += lvec.value(fct,dof); - - } - else if ( !m_myParticle->m_bDefectByHand ) - { - if ( dim == 3 ) - UG_THROW("in 'add_local_vec_to_global': NOT implemented for 3d!...EXIT!..\n"); - - // CHECK for elements, cut by two different particles: - if ( prtIndex_ref == -1 ) - prtIndex_ref = prtIndex; - - // get ExtraIndices - for WRITING DoFRef(vec,ind): - DoFIndex transInd = m_myParticle->get_transInd_Comp(Index, prtIndex, fct); - DoFIndex rotInd = m_myParticle->get_rotInd_Comp(Index, prtIndex, 0); - - MathVector RotVec; - size_t cmp; - - - // FIRST: get radialVector before adding to global vector - DoFIndex Ind = m_myParticle->m_vvvIndexRadialPair_List[Index][prtIndex][indexList1].first; - MathVector radialVector = m_myParticle->m_vvvIndexRadialPair_List[Index][prtIndex][indexList1].second; - RotVec[0] = -radialVector[1]; - RotVec[1] = radialVector[0]; - cmp = Ind[1]; - - - // SECOND: adding to global vector - // ADD to Trans: - DoFRef(vec, transInd) += lvec.value(fct,dof); - // ADD to Rot: - DoFRef(vec, rotInd) += lvec.value(fct,dof)*RotVec[cmp]; - - } // end else - - - } // end dof-loop - } // end fct-loop - - -} -*/ - -} // end namespace NavierStokes -} // end namespace ug - - - -#endif /* PARTICLE_MAPPER_TOOLS_H_ */ diff --git a/incompressible/fv1/moving_particle/meanID_tools.h b/incompressible/fv1/moving_particle/meanID_tools.h deleted file mode 100644 index ee3376a..0000000 --- a/incompressible/fv1/moving_particle/meanID_tools.h +++ /dev/null @@ -1,1732 +0,0 @@ -/* - * moving_particle_tools.h - * - * Created on: 20.01.2015 - * Author: suze - */ - -#ifndef MEAN_ID_H_ -#define MEAN_ID_H_ - -namespace ug{ -namespace NavierStokes{ - -/* - - template - number MovingParticle:: - compute_functional_fixed(const size_t n, vector_type& u, SmartPtr > spApproxSpace, - SmartPtr > spMaster, const int topLevel) - { - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - - // get data - typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); - - // create Function Group - FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); - - // get subset handler - ConstSmartPtr rSH = dd->subset_handler(); - - // get iterators for all elems on subset - typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; - - typename DoFDistribution::traits::const_iterator iter, iterEnd; - iter = dd->begin(); - iterEnd = dd->end(); - - size_t numDoFs = 0.5 * (n+1) * (n+2); // = 45; 36 :) - - - number D_kVol = 0.0; - number D_kSurf = 0.0; - std::vector gradD(2*numDoFs, 0.0); - - size_t counterFixed = 0; - // loop elements in order to compute 'U_global' and 'omega_global': - for( ; iter != iterEnd; ++iter) - { - // get element - grid_base_object* elem = *iter; - - std::vector vVertex; - CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); - - // loop vertices - for (size_t v = 0; v < vVertex.size(); ++v) - { - UG_LOG("vrt_" << v << ": " << aaPos[vVertex[v]][0] << "\t" << aaPos[vVertex[v]][1] << "\n"); - } - - ////////////////////////////////////////////////// - // compute data: - std::vector > vCornerCoords; - CollectCornerCoordinates(vCornerCoords, *elem, aaPos, true); - - number areaTria = ElementSize(ROID_TRIANGLE, &vCornerCoords[0]); - - ////////////////////////////////////////////////// - // loop edges and: - // -> compute 'baseLineSquared', 'baseLine', 'dist' - // -> collect associated vertex 'vrtOut', 'vIndex_Out' - - std::vector vEdges; - CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); - - // values to be computed: - number baseLineSquared, baseLine; - MathVector dist; - size_t vIndex_Out; - Vertex* vrtOut; - - for(size_t e = 0; e < vEdges.size(); ++e) - { - Edge* edge = vEdges[e]; - - if ( rSH->get_subset_index(edge) != 3 ) - { - UG_LOG("...continue...subset = " << rSH->get_subset_index(edge) << "\n"); - continue; - } - - UG_LOG("subset = " << rSH->get_subset_index(edge) << "\n"); - - std::vector vVertexEdge; - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); - if ( vVertexEdge.size() != 2 ) - UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); - - Vertex* vrt1 = vVertexEdge[0]; - Vertex* vrt2 = vVertexEdge[1]; - - baseLineSquared = VecDistanceSq(aaPos[vrt1], aaPos[vrt2]); - baseLine = sqrt(baseLineSquared); - dist[0] = fabs(aaPos[vrt1][0] - aaPos[vrt2][0]); - dist[1] = fabs(aaPos[vrt1][1] - aaPos[vrt2][1]); - - // loop vertices and get vrtOut: - for (size_t v = 0; v < vVertex.size(); ++v) - { - if ( (vVertex[v] != vrt1) && (vVertex[v] != vrt2) ) - { - vrtOut = vVertex[v]; - vIndex_Out = v; - } - } - - UG_LOG("vrt1: " << aaPos[vrt1][0] << "\t" << aaPos[vrt1][1] << "\n"); - UG_LOG("vrt2: " << aaPos[vrt2][0] << "\t" << aaPos[vrt2][1] << "\n"); - UG_LOG("vrtOut: " << aaPos[vrtOut][0] << "\t" << aaPos[vrtOut][1] << "\n"); - - } // end edge-loop - UG_LOG("new edge\n"); - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // (1) functional computations: - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////// - // volume computations: - if ( rSH->get_subset_index(elem) == 0 ) - - { - D_kVol += 0.5 * baseLineSquared/areaTria; - } - ////////////////////////////////////////////////// - // surface computations: - else if ( rSH->get_subset_index(elem) == 4 ) - { - D_kSurf += 0.5 * baseLineSquared/areaTria; - } - else { - UG_LOG("elem subset index = " << rSH->get_subset_index(elem) << "\n"); - - UG_THROW("why more than 2 subsets possible?\n"); - } - - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // (2) gradient computations: - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////// - // (1) get global indices of vrt1, vrt2, vrtOut for final adding up to DoF-vector in (4): - - std::vector Ind; - dd->dof_indices(elem, 1, Ind); // #instead-ToDo: dd->dof_indices(elem, cmp, Ind); - - for (size_t v = 0; v < vVertex.size(); ++v) - UG_LOG("2 Ind = " << Ind[v] << "\n"); - - - - //////////////////////////////////////////////////////////////////////////////// - // #instead-ToDo: loop components 'cmp' = x- and y-direction: - for (size_t cmp = 0; cmp < dim; ++cmp) - { - for (size_t v = 0; v < vVertex.size(); ++v) - { - - std::vector vInd; - if(dd->inner_dof_indices(vVertex[v], cmp, vInd) != 1) - UG_THROW("1: error in inner_dof_indices operatio!\n"); - - size_t Index = Ind[v][0]; - - - UG_LOG("Index = " << Index << "\n"); - UG_LOG("vInd_0[0] = " << vInd[0] << "\n"); - - - // boundary nodes are fixed and therefore no DoFs: - if ( rSH->get_subset_index(vVertex[v]) == 1 || rSH->get_subset_index(vVertex[v]) == 2 || rSH->get_subset_index(vVertex[v]) == 3 || rSH->get_subset_index(vVertex[v]) == 5 ) - { - DoFRef(u, vInd[0]) = 0.0; - - ++counterFixed; - continue; - } - - ////////////////////////////////////////////////// - // (2) data to be computed for the gradient computations - number gradD_elem; - number gradA_elem; - - // get indices modulo 2 - size_t index_1 = (v+1)%3; - size_t index_2 = (v+2)%3; - - gradA_elem = fabs(aaPos[vVertex[index_1]][(cmp+1)%2] - aaPos[vVertex[index_2]][(cmp+1)%2]); - - - // ToDo: Vorzeichen für Ableitung von Area A(x1, x2, x3) checken: wirkliche fabs()? - - if ( (vVertex[v] != vrtOut) ) - { - if ( v == vIndex_Out ) UG_THROW("1: error in vIndex_Out computation!\n"); - - gradD_elem = 2*dist[cmp]; - } - else - { - if ( v != vIndex_Out ) UG_THROW("2: error in vIndex_Out computation!\n"); - - gradD_elem = 0.0; - } - - - - ////////////////////////////////////////////////// - // (3) gradient computations: - - - ////////////////////////////////////////////////// - // (3.1) volume computations: - if ( rSH->get_subset_index(elem) == 0 ) - - { - UG_LOG("elem subset index = 0:" << rSH->get_subset_index(elem) << "\n"); - - number gradD_kVol = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); - - ////////////////////////////////////////////////// - // (4) add up all computations to entry of DoF-vector: - // gradD[Index] += gradD_kVol_x/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... - // gradD[numDoFs + Index] += gradD_kVol_y/(n*n); // ToDo! - DoFRef(u, vInd[0]) += (-1.0) * gradD_kVol/(n*n); - } - - ////////////////////////////////////////////////// - // (3.2) surface computations: - else if ( rSH->get_subset_index(elem) == 4 ) - { - UG_LOG("elem subset index = 4:" << rSH->get_subset_index(elem) << "\n"); - - number gradD_kSurf = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); - - ////////////////////////////////////////////////////////// - // (4) add up all computations to entry of DoF-vector: - // gradD[Index] -= gradD_kSurf_x*(n-1)/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... - // gradD[numDoFs + Index] -= gradD_kSurf_y*(n-1)/(n*n); // ToDo! - DoFRef(u, vInd[0]) -= (-1.0) * gradD_kSurf*(n-1)/(n*n); - } - else - { - UG_LOG("elem subset index = " << rSH->get_subset_index(elem) << "\n"); - UG_THROW("--> why more than 2 subsets possible?\n"); - } - - - - UG_LOG("\n ---> v = " << v << " and Ind = " << Ind[v] << "\n"); - - }// end vrt-loop - - }// end cmp-loop - - } // end elem-loop - - number functional = D_kVol/(n*n) - D_kSurf*(n-1)/(n*n); - - UG_LOG("counterFixed = " << counterFixed << "\n"); - - return functional; - - } -*/ -/* - template - number MovingParticle:: - compute_functional_combined(const size_t n, vector_type& u, SmartPtr > spApproxSpace, - SmartPtr > spMaster, const int topLevel) - { - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - - // get data - typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); - - // create Function Group - FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); - - // get subset handler - ConstSmartPtr rSH = dd->subset_handler(); - - // get iterators for all elems on subset - typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; - - typename DoFDistribution::traits::const_iterator iter, iterEnd; - iter = dd->begin(); - iterEnd = dd->end(); - - size_t numDoFs = 0.5 * (n+1) * (n+2); // = 45; 36 :) - - - number D_kVol = 0.0; - number D_kSurf = 0.0; - std::vector gradD(2*numDoFs, 0.0); - - // loop elements in order to compute 'U_global' and 'omega_global': - for( ; iter != iterEnd; ++iter) - { - // get element - grid_base_object* elem = *iter; - - std::vector vVertex; - CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); - - // loop vertices - for (size_t v = 0; v < vVertex.size(); ++v) - { - UG_LOG("vrt_" << v << ": " << aaPos[vVertex[v]][0] << "\t" << aaPos[vVertex[v]][1] << "\n"); - } - - ////////////////////////////////////////////////// - // compute data: - std::vector > vCornerCoords; - CollectCornerCoordinates(vCornerCoords, *elem, aaPos, true); - - number areaTria = ElementSize(ROID_TRIANGLE, &vCornerCoords[0]); - - ////////////////////////////////////////////////// - // loop edges and: - // -> compute 'baseLineSquared', 'baseLine', 'dist' - // -> collect associated vertex 'vrtOut', 'vIndex_Out' - - std::vector vEdges; - CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); - - // values to be computed: - number baseLineSquared, baseLine; - MathVector dist; - size_t vIndex_Out; - Vertex* vrtOut; - - for(size_t e = 0; e < vEdges.size(); ++e) - { - Edge* edge = vEdges[e]; - - if ( rSH->get_subset_index(edge) != 3 ) - { - UG_LOG("...continue...subset = " << rSH->get_subset_index(edge) << "\n"); - continue; - } - - UG_LOG("subset = " << rSH->get_subset_index(edge) << "\n"); - - std::vector vVertexEdge; - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); - if ( vVertexEdge.size() != 2 ) - UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); - - Vertex* vrt1 = vVertexEdge[0]; - Vertex* vrt2 = vVertexEdge[1]; - - baseLineSquared = VecDistanceSq(aaPos[vrt1], aaPos[vrt2]); - baseLine = sqrt(baseLineSquared); - dist[0] = fabs(aaPos[vrt1][0] - aaPos[vrt2][0]); - dist[1] = fabs(aaPos[vrt1][1] - aaPos[vrt2][1]); - - // loop vertices and get vrtOut: - for (size_t v = 0; v < vVertex.size(); ++v) - { - if ( (vVertex[v] != vrt1) && (vVertex[v] != vrt2) ) - { - vrtOut = vVertex[v]; - vIndex_Out = v; - } - } - - UG_LOG("vrt1: " << aaPos[vrt1][0] << "\t" << aaPos[vrt1][1] << "\n"); - UG_LOG("vrt2: " << aaPos[vrt2][0] << "\t" << aaPos[vrt2][1] << "\n"); - UG_LOG("vrtOut: " << aaPos[vrtOut][0] << "\t" << aaPos[vrtOut][1] << "\n"); - - } // end edge-loop - UG_LOG("new edge\n"); - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // (1) functional computations: - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////// - // volume computations: - if ( rSH->get_subset_index(elem) == 0 ) - - { - D_kVol += 0.5 * baseLineSquared/areaTria; - } - ////////////////////////////////////////////////// - // surface computations: - else if ( rSH->get_subset_index(elem) == 4 ) - { - D_kSurf += 0.5 * baseLineSquared/areaTria; - } - else { - UG_LOG("elem subset index = " << rSH->get_subset_index(elem) << "\n"); - - UG_THROW("why more than 2 subsets possible?\n"); - } - - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // (2) gradient computations: - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////// - // (1) get global indices of vrt1, vrt2, vrtOut for final adding up to DoF-vector in (4): - - std::vector Ind; - dd->dof_indices(elem, 1, Ind); // #instead-ToDo: dd->dof_indices(elem, cmp, Ind); - - for (size_t v = 0; v < vVertex.size(); ++v) - UG_LOG("2 Ind = " << Ind[v] << "\n"); - - - number _A_ = (aaPos[vVertex[1]][1]-aaPos[vVertex[0]][1])*(aaPos[vVertex[2]][0]-aaPos[vVertex[0]][0]) - -(aaPos[vVertex[1]][0]-aaPos[vVertex[0]][0])*(aaPos[vVertex[2]][1]-aaPos[vVertex[0]][1]); - - number gradA_scale = 0.5 * _A_ / fabs(_A_); - - // if ( gradA_scale > 0 ) - // UG_LOG("gradA_scale = " << gradA_scale << "\n"); - - //////////////////////////////////////////////////////////////////////////////// - // #instead-ToDo: loop components 'cmp' = x- and y-direction: - for (size_t cmp = 0; cmp < dim; ++cmp) - { - for (size_t v = 0; v < vVertex.size(); ++v) - { - std::vector vInd; - if(dd->inner_dof_indices(vVertex[v], cmp, vInd) != 1) - UG_THROW("1: error in inner_dof_indices operatio!\n"); - - size_t Index = Ind[v][0]; - - - UG_LOG("Index = " << Index << "\n"); - UG_LOG("vInd_0[0] = " << vInd[0] << "\n"); - - ////////////////////////////////////////////////// - // (2) data to be computed for the gradient computations - number gradD_elem; - number gradA_elem; - - // get indices modulo 2 - size_t ind_1 = (v+1)%3; - size_t ind_2 = (v+2)%3; - size_t cmp_shift = (cmp+1)%2; - - UG_LOG("-------> cmp_shift = " << cmp_shift << "\n"); - - - if ( cmp_shift == 0 ) // ind_2 - ind_1 - gradA_elem = 0.5 * aaPos[vVertex[ind_2]][cmp_shift] - aaPos[vVertex[ind_1]][cmp_shift]; - else if ( cmp_shift == 1 ) // ind_1 - ind_2 - gradA_elem = 0.5 * aaPos[vVertex[ind_1]][cmp_shift] - aaPos[vVertex[ind_2]][cmp_shift]; - else UG_THROW("cmp_shift not valid: " << cmp_shift << "\n"); - - //gradA_elem = 0.5 * aaPos[vVertex[ind_1]][(cmp+1)%2] - aaPos[vVertex[ind_2]][(cmp+1)%2]); - UG_LOG("-------> gradA_elem = " << gradA_elem << "\n"); - - //gradA_elem *= gradA_scale; - - - // ToDo: Vorzeichen für Ableitung von Area A(x1, x2, x3) checken: wirkliche fabs()? - - if ( (vVertex[v] != vrtOut) ) - { - if ( v == vIndex_Out ) UG_THROW("1: error in vIndex_Out computation!\n"); - - gradD_elem = 2*dist[cmp]; - } - else - { - if ( v != vIndex_Out ) UG_THROW("2: error in vIndex_Out computation!\n"); - - gradD_elem = 0.0; - } - - - - ////////////////////////////////////////////////// - // (3) gradient computations: - - - ////////////////////////////////////////////////// - // (3.1) volume computations: - if ( rSH->get_subset_index(elem) == 0 ) - - { - UG_LOG("elem subset index = 0:" << rSH->get_subset_index(elem) << "\n"); - - number gradD_kVol = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); - - ////////////////////////////////////////////////// - // (4) add up all computations to entry of DoF-vector: - // gradD[Index] += gradD_kVol_x/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... - // gradD[numDoFs + Index] += gradD_kVol_y/(n*n); // ToDo! - DoFRef(u, vInd[0]) += (-1.0) * gradD_kVol/(n*n); - if ( vInd[0][0] == 18 && cmp == 0 ) - { - UG_LOG("gradD_elem = " << gradD_elem << "\n"); - UG_LOG("gradA_elem = " << gradA_elem << "\n"); - UG_LOG("gradA_scale = " << gradA_scale << "\n"); - UG_LOG("areaTria = " << areaTria << "\n"); - UG_LOG("baseLineSquared = " << baseLineSquared << "\n"); - - UG_LOG("gradD_kVol = " << gradD_kVol << "\n"); - UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); - } - } - - ////////////////////////////////////////////////// - // (3.2) surface computations: - else if ( rSH->get_subset_index(elem) == 4 ) - { - UG_LOG("elem subset index = 4:" << rSH->get_subset_index(elem) << "\n"); - - number gradD_kSurf = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); - - ////////////////////////////////////////////////////////// - // (4) add up all computations to entry of DoF-vector: - // gradD[Index] -= gradD_kSurf_x*(n-1)/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... - // gradD[numDoFs + Index] -= gradD_kSurf_y*(n-1)/(n*n); // ToDo! - DoFRef(u, vInd[0]) -= (-1.0) * gradD_kSurf*(n-1)/(n*n); - if ( vInd[0][0] == 18 && cmp == 0 ) - { - UG_LOG("gradD_elem = " << gradD_elem << "\n"); - UG_LOG("gradA_elem = " << gradA_elem << "\n"); - UG_LOG("gradA_scale = " << gradA_scale << "\n"); - UG_LOG("areaTria = " << areaTria << "\n"); - UG_LOG("baseLineSquared = " << baseLineSquared << "\n"); - - UG_LOG("gradD_kSurf = " << gradD_kSurf << "\n"); - UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); - } - } - else - { - UG_LOG("elem subset index = " << rSH->get_subset_index(elem) << "\n"); - UG_THROW("--> why more than 2 subsets possible?\n"); - } - - - - UG_LOG("\n ---> v = " << v << " and Ind = " << Ind[v] << "\n"); - - }// end vrt-loop - - }// end cmp-loop - - } // end elem-loop - - number functional = D_kVol/(n*n) - D_kSurf*(n-1)/(n*n); - functional *= functional; - - return functional; - - } - */ - -template -number MovingParticle:: -compute_functional_all(const size_t n, vector_type& u, SmartPtr > spApproxSpace, - SmartPtr > spMaster, const int topLevel) -{ - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - - // get data - typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); - - // create Function Group - FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); - - // get subset handler - ConstSmartPtr rSH = dd->subset_handler(); - - // get iterators for all elems on subset - typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; - - typename DoFDistribution::traits::const_iterator iter, iterEnd; - iter = dd->begin(); - iterEnd = dd->end(); - - size_t numDoFs = 0.5 * (n+1) * (n+2); // = 45; 36 :) - - number D_kVol = 0.0; - number D_kSurf = 0.0; - std::vector gradD(2*numDoFs, 0.0); - - int counter1, counter2, counter3, counter0, counter5; - counter1 = counter2 = counter3 = counter5 = counter0 = 0; - - - // loop elements in order to compute 'U_global' and 'omega_global': - for( ; iter != iterEnd; ++iter) - { - counter0 += 1; - // get element - grid_base_object* elem = *iter; - - std::vector vVertex; - CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); - for (size_t v = 0; v < vVertex.size(); ++v) - UG_LOG("vrt_" << v << ": " << aaPos[vVertex[v]][0] << "\t" << aaPos[vVertex[v]][1] << "\n"); - - - ////////////////////////////////////////////////// - // compute data: - std::vector > vCornerCoords; - CollectCornerCoordinates(vCornerCoords, *elem, aaPos, true); - - number areaTria = ElementSize(ROID_TRIANGLE, &vCornerCoords[0]); - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // (1) functional computations: - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////// - // volume computations ---> ALWAYS!! - - std::vector vEdges; - CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); - - // loop edges - for(size_t e = 0; e < vEdges.size(); ++e) - { - Edge* edge = vEdges[e]; - - std::vector vVertexEdge; - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); - if ( vVertexEdge.size() != 2 ) - UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); - - number baseLineSquared = VecDistanceSq(aaPos[vVertexEdge[0]], aaPos[vVertexEdge[1]]); - - D_kVol += baseLineSquared/(2*areaTria); - - } - - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // surface computations - again: - - //////////////////////////////////////////////////////////////////////////////// - // FIRST: get subSet of boundary element (exclude inner elements (0) ) - int subSet = rSH->get_subset_index(elem); - - //////////////////////////////////////////////////////////////////////////////// - // data filled for subSet = 1,2,3 and 5 - // AND needed for later computations! - size_t indexA, indexB, indexC; - std::vector vEdgesS(3); - std::vector vBaseLine(3); - number sSq = 0.0; - number sSq_all = 0.0; - - std::vector vEdges_buffer; - CollectEdgesSorted(vEdges_buffer, *m_spParticleHandlerGlobal->m_spMG, elem); - - if ( subSet == 5 ) - { - counter5 += 1; - // collect all vertices of the element - std::vector vVertexS_buffer; - std::vector vVertexS(3); - CollectVertices(vVertexS_buffer, *m_spParticleHandlerGlobal->m_spMG, elem); - - // loop all vertices; treat them as vertex A as in the case below; add up and weight with 1/3: - for(size_t countA = 0; countA < 3; ++countA) - { - // now store the other indices in order: - indexA = countA; - indexC = (countA+1)%3; - indexB = (countA+2)%3; - - //////////////////////////////////////////////////////////////////////////////// - // (1) collect 'vVertexS': - vVertexS[0] = vVertexS_buffer[indexA]; - vVertexS[1] = vVertexS_buffer[indexC]; - vVertexS[2] = vVertexS_buffer[indexB]; - - UG_LOG("---------> vVertexS: " << aaPos[vVertexS[0]][0] << "\t" << aaPos[vVertexS[0]][1] << "\n"); - UG_LOG("---------> vVertexS: " << aaPos[vVertexS[1]][0] << "\t" << aaPos[vVertexS[1]][1] << "\n"); - UG_LOG("---------> vVertexS: " << aaPos[vVertexS[2]][0] << "\t" << aaPos[vVertexS[2]][1] << "\n"); - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // (B) loop edges ---> for boundary elements with subset 'subSet': - - // loop edges - for(size_t e = 0; e < vEdges_buffer.size(); ++e) - { - Edge* edge = vEdges_buffer[e]; - - std::vector vVertexEdge; - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); - if ( vVertexEdge.size() != 2 ) - UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); - - // choose the edge, which does NOT contain the vertex A: - if ( (vVertexEdge[0] != vVertexS[0]) && (vVertexEdge[1] != vVertexS[0]) ) - { - vEdgesS[0] = edge; - indexA = e; - break; - } - } - // now store the other indices in order: - indexB = (indexA+1)%3; - indexC = (indexA+2)%3; - - //ToDo: egal, was indexB und indexC ist, solange NICHT indexA = subSet?? - - //////////////////////////////////////////////////////////////////////////////// - // (2) collect 'vEdgesS': - vEdgesS[1] = vEdges_buffer[indexB]; - vEdgesS[2] = vEdges_buffer[indexC]; - - //////////////////////////////////////////////////////////////////////////////// - // (3) collect 'vBaseLine': - for(size_t i = 0; i < 3; ++i) - { - std::vector vVertexEdge; - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, vEdgesS[i]); - if ( vVertexEdge.size() != 2 ) - UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); - - UG_LOG("---------> vVertexEdge1: " << aaPos[vVertexEdge[0]][0] << "\t" << aaPos[vVertexEdge[0]][1] << "\n"); - UG_LOG("---------> vVertexEdge2: " << aaPos[vVertexEdge[1]][0] << "\t" << aaPos[vVertexEdge[1]][1] << "\n"); - - number baseLineSquared = VecDistanceSq(aaPos[vVertexEdge[0]], aaPos[vVertexEdge[1]]); - vBaseLine[i] = sqrt(baseLineSquared); - } - - //////////////////////////////////////////////////////////////////////////////// - // THIRD: compute data for surface integrals ---> s, alphaB, alphaC - - number a = vBaseLine[0]; - number b = vBaseLine[1]; - number c = vBaseLine[2]; - number aSq = a*a; - number bSq = b*b; - number cSq = c*c; - - number s = 0.5*sqrt(2 * (bSq+cSq) - aSq); - sSq = s*s; - sSq_all += sSq; - UG_LOG("---------> sSq: " << sSq << "\n"); - UG_LOG("---------> sSq_all: " << sSq_all << "\n"); - - number cosAlphaB = (bSq + sSq - 0.25*aSq)/(2*b*s); - number cosAlphaC = (cSq + sSq - 0.25*aSq)/(2*c*s); - - //////////////////////////////////////////////////////////////////////////////// - // FINALLY: compute fluxes - - number fluxB = 0.5*s*b*cosAlphaB/areaTria ; - number fluxC = 0.5*s*c*cosAlphaC/areaTria ; - - D_kSurf += (fluxB + fluxC)/3.0; - - number added = (fluxB + fluxC)/3.0;; - UG_LOG("subSet = " << subSet << "added = " << added << "\n"); - - } // end indexA-loop - } // end case subSet == 5 - - - //////////////////////////////////////////////////////////////////////////////// - // SECOND: loop vertices AND edges --> write data according to specified indices 'indexA, indexB, indexC': - - if ( subSet == 1 ) counter1 += 1; - if ( subSet == 2 ) counter2 += 1; - if ( subSet == 3 ) counter3 += 1; - - //////////////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // loop edges ---> for boundary elements with subset 'subSet': - - //////////////////////////////////////////////////////////////////////////////// - // THIRD: compute data for surface integrals ---> s, alphaB, alphaC - - if ( subSet == 1 || subSet == 2 || subSet == 3 ) - { - - // loop edges - for(size_t e = 0; e < vEdges_buffer.size(); ++e) - { - if ( rSH->get_subset_index(vEdges_buffer[e]) == subSet ) - { - vEdgesS[0] = vEdges_buffer[e]; - indexA = e; - break; - } - } - // now store the other indices in order: - indexB = (indexA+1)%3; - indexC = (indexA+2)%3; - - //ToDo: egal, was indexB und indexC ist, solange NICHT indexA = subSet?? - - //////////////////////////////////////////////////////////////////////////////// - // (2) collect 'vEdgesS': - vEdgesS[1] = vEdges_buffer[indexB]; - vEdgesS[2] = vEdges_buffer[indexC]; - - //////////////////////////////////////////////////////////////////////////////// - // (3) collect 'vBaseLine': - for(size_t i = 0; i < 3; ++i) - { - std::vector vVertexEdge; - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, vEdgesS[i]); - if ( vVertexEdge.size() != 2 ) - UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); - - UG_LOG("---------> vVertexEdge1: " << aaPos[vVertexEdge[0]][0] << "\t" << aaPos[vVertexEdge[0]][1] << "\n"); - UG_LOG("---------> vVertexEdge2: " << aaPos[vVertexEdge[1]][0] << "\t" << aaPos[vVertexEdge[1]][1] << "\n"); - - number BaseLineSquared = VecDistanceSq(aaPos[vVertexEdge[0]], aaPos[vVertexEdge[1]]); - vBaseLine[i] = sqrt(BaseLineSquared); - - } - - number a = vBaseLine[0]; - number b = vBaseLine[1]; - number c = vBaseLine[2]; - number aSq = a*a; - number bSq = b*b; - number cSq = c*c; - - number s = 0.5*sqrt(2 * (bSq+cSq) - aSq); - sSq = s*s; - number cosAlphaB = (bSq + sSq - 0.25*aSq)/(2*b*s); - number cosAlphaC = (cSq + sSq - 0.25*aSq)/(2*c*s); - - //////////////////////////////////////////////////////////////////////////////// - // FINALLY: compute fluxes - - number fluxB_ = 0.5*s*b*cosAlphaB/areaTria ; - number fluxC_ = 0.5*s*c*cosAlphaC/areaTria ; - - number fluxB = 0.5*0.25*(3*bSq + cSq - aSq)/areaTria ; - number fluxC = 0.5*0.25*(3*cSq + bSq - aSq)/areaTria ; - - if ( fabs(fluxB - fluxB_) > 0.00001 ) - UG_THROW(" fluxB: " << fluxB << " and " << " fluxB_: " << fluxB_ << "\n"); - if ( fabs(fluxC - fluxC_) > 0.00001 ) - UG_THROW(" fluxC: " << fluxC << " and " << " fluxC_: " << fluxC_ << "\n"); - - D_kSurf += fluxB + fluxC; - number added = fluxB + fluxC; - UG_LOG("subSet = " << subSet << "added = " << added << "\n"); - - - } // END: functional computations - - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // compute gradients - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////////////// - // compute scaling for gradA_elem: - - number _A_ =(aaPos[vVertex[1]][0]-aaPos[vVertex[0]][0])*(aaPos[vVertex[2]][1]-aaPos[vVertex[0]][1]) - -(aaPos[vVertex[2]][0]-aaPos[vVertex[0]][0])*(aaPos[vVertex[1]][1]-aaPos[vVertex[0]][1]); - - number gradA_scale = _A_ / fabs(_A_); - - //////////////////////////////////////////////////////////////////////////////// - // loop cmp and vertices to compute 'gradS_elem' and - // ADD 'gradA_elem'/'gradA_elem' to gradient: - - number gradA_elem; - number gradD_elem_all; - number gradS_elem; - std::vector vVertexEdge; - - for (size_t cmp = 0; cmp < dim; ++cmp) - { - - for (size_t v = 0; v < vVertex.size(); ++v) - { - std::vector vInd; - if(dd->inner_dof_indices(vVertex[v], cmp, vInd) != 1) - UG_THROW("1: error in inner_dof_indices operatio!\n"); - - UG_LOG("vInd[0] = " << vInd[0] << "\n"); - - //////////////////////////////////////////////////////////////////////////////// - // initialize gradient for the denominator and add all the contributions from the edges - gradS_elem = 0.0; - gradD_elem_all = 0.0; - - //////////////////////////////////////////////////////////////////////////////// - // compute 'gradA_elem': - - // get indices modulo 2 - size_t ind_1 = (v+1)%3; - size_t ind_2 = (v+2)%3; - size_t cmp_shift = (cmp+1)%2; - - // ind_2 - ind_1 - if ( cmp_shift == 0 ) - gradA_elem = 0.5 * (aaPos[vVertex[ind_2]][cmp_shift] - aaPos[vVertex[ind_1]][cmp_shift]); - // ind_1 - ind_2 - else if ( cmp_shift == 1 ) - gradA_elem = 0.5 * (aaPos[vVertex[ind_1]][cmp_shift] - aaPos[vVertex[ind_2]][cmp_shift]); - else - UG_THROW("cmp_shift not valid: " << cmp_shift << "\n"); - - gradA_elem *= gradA_scale; - - - //////////////////////////////////////////////////////////////////////////////// - // compute 'gradS_elem' and 'gradD_elem_all': - - ////////////////////////////////////////////////// - // edge contributions: - - number gradS_elem_scale = 1.0; - std::vector vBaseLineSquared(3); - - if ( subSet == 5 ) - { UG_LOG("---> elem subset index = :" << rSH->get_subset_index(elem) << "\n");} - - for(size_t e = 0; e < 3; ++e) - { - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, vEdges_buffer[e]); - if ( vVertexEdge.size() != 2 ) - UG_THROW("---> error in collecting vertices associated to an edge!....EXIT!...\n"); - - vBaseLineSquared[e] = VecDistanceSq(aaPos[vVertexEdge[0]], aaPos[vVertexEdge[1]]); - - UG_LOG("for 'gradS_elem_scale': vVertexEdge1: " << aaPos[vVertexEdge[0]][0] << "\t" << aaPos[vVertexEdge[0]][1] << "\n"); - UG_LOG("for 'gradS_elem_scale': vVertexEdge2: " << aaPos[vVertexEdge[1]][0] << "\t" << aaPos[vVertexEdge[1]][1] << "\n"); - - - // adapt scale factor for edge = baseLine: - if ( rSH->get_subset_index(vEdges_buffer[e]) == 5 ) - UG_THROW("---> hmmmm: EDGE subset index can NOT be 5! ---> index = :" << rSH->get_subset_index(vEdges_buffer[e]) << "\n"); - - if ( rSH->get_subset_index(vEdges_buffer[e]) == subSet ) - gradS_elem_scale = -0.5; - if ( subSet == 5 ) - gradS_elem_scale = 1.5; - - if ( vVertex[v] == vVertexEdge[0] ) - { - gradS_elem += gradS_elem_scale * 2.0 * (aaPos[vVertexEdge[0]][cmp] - aaPos[vVertexEdge[1]][cmp]); - gradD_elem_all += 2.0 * (aaPos[vVertexEdge[0]][cmp] - aaPos[vVertexEdge[1]][cmp]); - } - else if ( vVertex[v] == vVertexEdge[1] ) - { - gradS_elem += gradS_elem_scale * 2.0 * (aaPos[vVertexEdge[1]][cmp] - aaPos[vVertexEdge[0]][cmp]); - gradD_elem_all += 2.0 * (aaPos[vVertexEdge[0]][cmp] - aaPos[vVertexEdge[1]][cmp]); - } - // else: add 0.0 ==> do nothing... - - } // end edge-loop - - number vBaseLineSquared_all = vBaseLineSquared[0] + vBaseLineSquared[1] + vBaseLineSquared[2]; - - - //////////////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////////////// - // ADD up all v-th derivatives to 'cmp' of vector 'u': - - ////////////////////////////////////////////////// - // (3.1) volume computations: - - number gradD_kVol = (areaTria*gradD_elem_all - vBaseLineSquared_all*gradA_elem)/(2*areaTria*areaTria); - - DoFRef(u, vInd[0]) += (-1.0) * gradD_kVol/(n*n); - - if (vInd[0][0] == 18 ) - UG_LOG("18: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); - - if (vInd[0][0] == 19 ) - UG_LOG("19: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); - - if (vInd[0][0] == 20 ) - UG_LOG("20: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); - - - if (vInd[0][0] == 21 ) - UG_LOG("21: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); - - - if (vInd[0][0] == 24 ) - UG_LOG("24: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); - - if (vInd[0][0] == 16 ) - UG_LOG("16: added: " << (-1.0) * gradD_kVol/(n*n) << "\t value: " << DoFRef(u, vInd[0]) << "\n"); - - - if ( vInd[0][0] == 18 && cmp == 0 ) - { - UG_LOG("gradD_elem_all = " << gradD_elem_all << "\n"); - UG_LOG("gradA_elem = " << gradA_elem << "\n"); - UG_LOG("gradA_scale = " << gradA_scale << "\n"); - UG_LOG("areaTria = " << areaTria << "\n"); - UG_LOG("vBaseLineSquared_all = " << vBaseLineSquared_all << "\n"); - - UG_LOG("gradD_kVol = " << gradD_kVol << "\n"); - UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); - } - - ////////////////////////////////////////////////// - // (3.2) surface computations: - if ( 0 ) //rSH->get_subset_index(elem) != 0 ) - { - if ( subSet != 1 && subSet != 2 && subSet != 3 ) - { - if ( subSet == 5 ) - { - sSq = sSq_all/3.0; - gradS_elem = gradS_elem/3.0; - UG_LOG("elem subset index = :" << rSH->get_subset_index(elem) << "\n"); - } - else - { UG_THROW("elem subset index = :" << rSH->get_subset_index(elem) << "\n");} - } - - number gradS_kSurf = 0.5 * (areaTria*gradS_elem - sSq*gradA_elem)/(areaTria*areaTria); - - DoFRef(u, vInd[0]) -= (-1.0) * gradS_kSurf/n; - if ( vInd[0][0] == 18 && cmp == 0 ) - { - UG_LOG("gradS_elem = " << gradS_elem << "\n"); - UG_LOG("gradA_elem = " << gradA_elem << "\n"); - UG_LOG("gradA_scale = " << gradA_scale << "\n"); - UG_LOG("areaTria = " << areaTria << "\n"); - - UG_LOG("gradS_kSurf = " << gradS_kSurf << "\n"); - UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); - } - } - - - }// end vrt-loop - - }// end cmp-loop - - } // end elem-loop - - number functional = 0.5 * D_kVol/(n*n) - D_kSurf/n; - functional *= functional; - - UG_LOG(" counter0: " << counter0 << "\n"); - UG_LOG(" counter1: " << counter1 << "\n"); - UG_LOG(" counter2: " << counter2 << "\n"); - UG_LOG(" counter3: " << counter3 << "\n"); - UG_LOG(" counter5: " << counter5 << "\n"); - - - return functional; - -} - - -template -number MovingParticle:: -compute_functional(const size_t n, vector_type& u, SmartPtr > spApproxSpace, - SmartPtr > spMaster, const int topLevel) -{ - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - - // get data - typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); - - // create Function Group - FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); - - // get subset handler - ConstSmartPtr rSH = dd->subset_handler(); - - // get iterators for all elems on subset - typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; - - typename DoFDistribution::traits::const_iterator iter, iterEnd; - iter = dd->begin(); - iterEnd = dd->end(); - - size_t numDoFs = 0.5 * (n+1) * (n+2); // = 45; 36 :) - - - number D_kVol = 0.0; - number D_kSurf = 0.0; - std::vector gradD(2*numDoFs, 0.0); - - // loop elements in order to compute 'U_global' and 'omega_global': - for( ; iter != iterEnd; ++iter) - { - // get element - grid_base_object* elem = *iter; - - std::vector vVertex; - CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); - - // loop vertices - for (size_t v = 0; v < vVertex.size(); ++v) - { - UG_LOG("vrt_" << v << ": " << aaPos[vVertex[v]][0] << "\t" << aaPos[vVertex[v]][1] << "\n"); - } - - ////////////////////////////////////////////////// - // compute data: - std::vector > vCornerCoords; - CollectCornerCoordinates(vCornerCoords, *elem, aaPos, true); - - number areaTria = ElementSize(ROID_TRIANGLE, &vCornerCoords[0]); - - ////////////////////////////////////////////////// - // loop edges and: - // -> compute 'baseLineSquared', 'baseLine', 'dist' - // -> collect associated vertex 'vrtOut', 'vIndex_Out' - - std::vector vEdges; - CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); - - // values to be computed: - number baseLineSquared, baseLine; - MathVector dist; - size_t vIndex_Out, vIndex_1, vIndex_2; - Vertex* vrtOut; - Vertex* vrt1; - Vertex* vrt2; - - for(size_t e = 0; e < vEdges.size(); ++e) - { - Edge* edge = vEdges[e]; - - if ( rSH->get_subset_index(edge) != 3 ) - { - UG_LOG("...continue...subset = " << rSH->get_subset_index(edge) << "\n"); - continue; - } - - UG_LOG("subset = " << rSH->get_subset_index(edge) << "\n"); - - std::vector vVertexEdge; - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); - if ( vVertexEdge.size() != 2 ) - UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); - - vrt1 = vVertexEdge[0]; - vrt2 = vVertexEdge[1]; - - baseLineSquared = VecDistanceSq(aaPos[vrt1], aaPos[vrt2]); - baseLine = sqrt(baseLineSquared); - dist[0] = fabs(aaPos[vrt1][0] - aaPos[vrt2][0]); - dist[1] = fabs(aaPos[vrt1][1] - aaPos[vrt2][1]); - - // loop vertices and get vrtOut: - for (size_t v = 0; v < vVertex.size(); ++v) - { - if ( (vVertex[v] != vrt1) && (vVertex[v] != vrt2) ) - { - vrtOut = vVertex[v]; - vIndex_Out = v; - } - if ( vVertex[v] == vrt1 ) - vIndex_1 = v; - if ( vVertex[v] == vrt2 ) - vIndex_2 = v; - } - - UG_LOG("vrt1: " << aaPos[vrt1][0] << "\t" << aaPos[vrt1][1] << "\n"); - UG_LOG("vrt2: " << aaPos[vrt2][0] << "\t" << aaPos[vrt2][1] << "\n"); - UG_LOG("vrtOut: " << aaPos[vrtOut][0] << "\t" << aaPos[vrtOut][1] << "\n"); - - } // end edge-loop - UG_LOG("new edge\n"); - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // (1) functional computations: - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////// - // volume computations ---> ALWAYS!! - if ( 1 ) //rSH->get_subset_index(elem) == 0 ) - - { - // Attention: the factor 1/2 is removed from D_kVol AND D_kSurf, since it arises in both summands! - D_kVol += baseLineSquared/(2.0*areaTria); - } - ////////////////////////////////////////////////// - // surface computations: - if ( rSH->get_subset_index(elem) == 4 ) - { - // Attention: the factor 1/2 is removed from D_kVol AND D_kSurf, since it arises in both summands! - D_kSurf += baseLineSquared/(2.0*areaTria); - } - - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - // (2) gradient computations: - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////// - // (1) get global indices of vrt1, vrt2, vrtOut for final adding up to DoF-vector in (4): - - std::vector Ind; - dd->dof_indices(elem, 1, Ind); // #instead-ToDo: dd->dof_indices(elem, cmp, Ind); - - for (size_t v = 0; v < vVertex.size(); ++v) - UG_LOG("2 Ind = " << Ind[v] << "\n"); - /* - template <> - inline number ElementSize(const MathVector<2>* vCornerCoords) - { - return(0.5*fabs((vCornerCoords[1][1]-vCornerCoords[0][1])*(vCornerCoords[2][0]-vCornerCoords[0][0]) - -(vCornerCoords[1][0]-vCornerCoords[0][0])*(vCornerCoords[2][1]-vCornerCoords[0][1]))); - } - */ - - number _A_ =(aaPos[vVertex[1]][0]-aaPos[vVertex[0]][0])*(aaPos[vVertex[2]][1]-aaPos[vVertex[0]][1]) - -(aaPos[vVertex[2]][0]-aaPos[vVertex[0]][0])*(aaPos[vVertex[1]][1]-aaPos[vVertex[0]][1]); - - number gradA_scale = _A_ / fabs(_A_); - - // if ( gradA_scale > 0 ) - // UG_LOG("gradA_scale = " << gradA_scale << "\n"); - - //////////////////////////////////////////////////////////////////////////////// - // #instead-ToDo: loop components 'cmp' = x- and y-direction: - for (size_t cmp = 0; cmp < dim; ++cmp) - { - for (size_t v = 0; v < vVertex.size(); ++v) - { - std::vector vInd; - if(dd->inner_dof_indices(vVertex[v], cmp, vInd) != 1) - UG_THROW("1: error in inner_dof_indices operatio!\n"); - - size_t Index = Ind[v][0]; - - - UG_LOG("Index = " << Index << "\n"); - UG_LOG("vInd_0[0] = " << vInd[0] << "\n"); - - ////////////////////////////////////////////////// - // (2) data to be computed for the gradient computations - number gradD_elem; - number gradA_elem; - - // get indices modulo 2 - size_t ind_1 = (v+1)%3; - size_t ind_2 = (v+2)%3; - size_t cmp_shift = (cmp+1)%2; - - UG_LOG("-------> cmp_shift = " << cmp_shift << "\n"); - - - if ( cmp_shift == 0 ) // ind_2 - ind_1 - gradA_elem = 0.5 * (aaPos[vVertex[ind_2]][cmp_shift] - aaPos[vVertex[ind_1]][cmp_shift]); - else if ( cmp_shift == 1 ) // ind_1 - ind_2 - gradA_elem = 0.5 * (aaPos[vVertex[ind_1]][cmp_shift] - aaPos[vVertex[ind_2]][cmp_shift]); - else UG_THROW("cmp_shift not valid: " << cmp_shift << "\n"); - - gradA_elem *= gradA_scale; - - - // ToDo: Vorzeichen für Ableitung von Area A(x1, x2, x3) checken: wirkliche fabs()? - - if ( vVertex[v] != vrtOut ) - { - if ( v == vIndex_Out ) UG_THROW("1: error in vIndex_Out computation!\n"); - - gradD_elem = 2.0 * (aaPos[vrt1][cmp] - aaPos[vrt2][cmp]); - - if ( vVertex[v] == vrt2 ) - { - gradD_elem *= -1.0; - UG_LOG("ind_1: " << ind_1 << "\n"); - UG_LOG("vIndex_1: " << vIndex_1 << "\n"); - UG_LOG("ind_2: " << ind_2 << "\n"); - UG_LOG("vIndex_2: " << vIndex_2 << "\n"); - } - - } - else - { - if ( v != vIndex_Out ) UG_THROW("2: error in vIndex_Out computation!\n"); - - gradD_elem = 0.0; - } - - - - ////////////////////////////////////////////////// - // (3) gradient computations: - - - ////////////////////////////////////////////////// - // (3.1) volume computations: - if ( 1 ) //rSH->get_subset_index(elem) == 0 ) - - { - UG_LOG("elem subset index = 0:" << rSH->get_subset_index(elem) << "\n"); - - number gradD_kVol = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); - - ////////////////////////////////////////////////// - // (4) add up all computations to entry of DoF-vector: - // gradD[Index] += gradD_kVol_x/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... - // gradD[numDoFs + Index] += gradD_kVol_y/(n*n); // ToDo! - DoFRef(u, vInd[0]) += (-1.0) * gradD_kVol/(n*n); - if ( vInd[0][0] == 18 && cmp == 0 ) - { - UG_LOG("gradD_elem = " << gradD_elem << "\n"); - UG_LOG("gradA_elem = " << gradA_elem << "\n"); - UG_LOG("gradA_scale = " << gradA_scale << "\n"); - UG_LOG("areaTria = " << areaTria << "\n"); - UG_LOG("baseLineSquared = " << baseLineSquared << "\n"); - - UG_LOG("gradD_kVol = " << gradD_kVol << "\n"); - UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); - } - } - - ////////////////////////////////////////////////// - // (3.2) surface computations: - if ( rSH->get_subset_index(elem) == 4 ) - { - UG_LOG("elem subset index = 4:" << rSH->get_subset_index(elem) << "\n"); - - number gradD_kSurf = (areaTria*gradD_elem - baseLineSquared*gradA_elem)/(2*areaTria*areaTria); - - ////////////////////////////////////////////////////////// - // (4) add up all computations to entry of DoF-vector: - // gradD[Index] -= gradD_kSurf_x*(n-1)/(n*n); // #instead-ToDo:: DoFRef(u, Ind[v]) += ... - // gradD[numDoFs + Index] -= gradD_kSurf_y*(n-1)/(n*n); // ToDo! - DoFRef(u, vInd[0]) -= (-1.0) * gradD_kSurf/n; - if ( vInd[0][0] == 18 && cmp == 0 ) - { - UG_LOG("gradD_elem = " << gradD_elem << "\n"); - UG_LOG("gradA_elem = " << gradA_elem << "\n"); - UG_LOG("gradA_scale = " << gradA_scale << "\n"); - UG_LOG("areaTria = " << areaTria << "\n"); - UG_LOG("baseLineSquared = " << baseLineSquared << "\n"); - - UG_LOG("gradD_kSurf = " << gradD_kSurf << "\n"); - UG_LOG("DoFRef(u, vInd[0][" << cmp << "]) = " << DoFRef(u, vInd[0]) << "\n"); - } - } - - - - UG_LOG("\n ---> v = " << v << " and Ind = " << Ind[v] << "\n"); - - }// end vrt-loop - - }// end cmp-loop - - } // end elem-loop - - // Attention: the factor 1/2 is removed from D_kVol AND D_kSurf, since it arises in both summands! - number functional = D_kVol/(n*n) - D_kSurf/n; - functional *= functional; - - return functional; - -} - -template -void MovingParticle:: -rescale_directions(const number functional, vector_type& u, SmartPtr > spApproxSpace, - SmartPtr > spMaster, const int topLevel) -{ - ///////////////////////////////////////////////// - // loop vertices and project directions - // of 'u' on outer boundary edges: - - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - DoFDistribution::traits::const_iterator iterBegin = dd->begin(); - DoFDistribution::traits::const_iterator iterEnd = dd->end(); - - // get subset handler - ConstSmartPtr rSH = dd->subset_handler(); - - number scaleFactor = sqrt(functional); - - // loop vertices - for(DoFDistribution::traits::const_iterator iter = iterBegin; iter != iterEnd; iter++) - { - // get vertex - Vertex* vrt = *iter; - - for (size_t cmp = 0; cmp < dim; ++cmp) - { - std::vector vInd; - if(dd->inner_dof_indices(vrt, cmp, vInd) != 1) - UG_THROW("1: error in inner_dof_indices operatio!\n"); - - DoFRef(u, vInd[0]) *= 2.0 * scaleFactor; - } - - - } // end vertices-loop - -} - -template -number MovingParticle:: -compute_max_step_size(SmartPtr > spApproxSpace, - SmartPtr > spMaster, const int topLevel) -{ - bool output = false; - - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - - // get data - typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); - - // create Function Group - FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); - - // get subset handler - ConstSmartPtr rSH = dd->subset_handler(); - - // get iterators for all elems on subset - typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; - - typename DoFDistribution::traits::const_iterator iter, iterEnd; - iter = dd->begin(); - iterEnd = dd->end(); - - // loop elements in order to compute minimal edge size: - number minEdgeSize = 1000.0; - int N = 0; - for( ; iter != iterEnd; ++iter) - { - // get element - grid_base_object* elem = *iter; - - ////////////////////////////////////////////////// - // loop edges and collect associated vertices 'vrt1' and 'vrt2' and 'vrtOut: - std::vector vEdges; - CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); - for(size_t e = 0; e < vEdges.size(); ++e) - { - Edge* edge = vEdges[e]; - - std::vector vVertexEdge; - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, edge); - if ( vVertexEdge.size() != 2 ) - UG_THROW("error in collecting vertices associated to an edge!....EXIT!...\n"); - - number edgeSize = VecDistance(aaPos[vVertexEdge[0]], aaPos[vVertexEdge[1]]); - - std::vector vInd1; - if(dd->inner_dof_indices(vVertexEdge[0], 0, vInd1) != 1) - UG_THROW("1: error in inner_dof_indices operatio!\n"); - std::vector vInd2; - if(dd->inner_dof_indices(vVertexEdge[1], 0, vInd2) != 1) - UG_THROW("1: error in inner_dof_indices operatio!\n"); - - if ( vInd1[0][0] == 11 || vInd2[0][0] == 11 ) - { - if ( vInd1[0][0] == 4 || vInd2[0][0] == 4 ) - { - //UG_LOG("minEdgeSize = " << minEdgeSize << "\n"); - //UG_LOG("aaPos[vVertexEdge[0]] = " << aaPos[vVertexEdge[0]][0] << "\t" << aaPos[vVertexEdge[0]][1] << "\n"); - //UG_LOG("aaPos[vVertexEdge[1]] = " << aaPos[vVertexEdge[1]][0] << "\t" << aaPos[vVertexEdge[1]][1] << "\n"); - - } - } - - - if ( minEdgeSize > edgeSize ) - { - minEdgeSize = edgeSize; - - if ( output ) UG_LOG("minEdgeSize = " << minEdgeSize << "\n"); - } - else - { - if ( output ) UG_LOG("--> edgeSize = " << edgeSize << "\n"); - - } - - }// end edge-loop - N = N+1; - - if ( output ) UG_LOG("--> new element: " << N << "\n"); - - }// end elem-loop - - UG_LOG("1 -----------> minEdgeSize = " << minEdgeSize << "\n"); - - return minEdgeSize; -} - - -template -void MovingParticle:: -project_directions(const number functional, vector_type& u, SmartPtr > spApproxSpace, - SmartPtr > spMaster, const int topLevel) -{ - ///////////////////////////////////////////////// - // loop vertices and project directions - // of 'u' on outer boundary edges: - - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - DoFDistribution::traits::const_iterator iterBegin = dd->begin(); - DoFDistribution::traits::const_iterator iterEnd = dd->end(); - - // get subset handler - ConstSmartPtr rSH = dd->subset_handler(); - - size_t counter1 = 0; - size_t counter2 = 0; - size_t counter3 = 0; - size_t counter4 = 0; - size_t counter5 = 0; - size_t counter6 = 0; - - // loop vertices - for(DoFDistribution::traits::const_iterator iter = iterBegin; iter != iterEnd; iter++) - { - // get vertex - Vertex* vrt = *iter; - - ///////////////////////////////////////////////// - // (1) get direction to be projected: - MathVector project; - - for (size_t cmp = 0; cmp < dim; ++cmp) - { - std::vector vInd; - if(dd->inner_dof_indices(vrt, cmp, vInd) != 1) - UG_THROW("1: error in inner_dof_indices operatio!\n"); - - project[cmp] = DoFRef(u, vInd[0]); - } - - ///////////////////////////////////////////////// - // (2) project according to projection edge: - MathVector edge; - // (2.1) project onto x-coordinate: (1,0) - if ( rSH->get_subset_index(vrt) == 3 ) - { - edge[0] = 1.0; edge[1] = 0.0; - number scalar = VecProd(project, edge); - - VecScale(project, edge, scalar); - ++counter1; - //project[1] = 0.0; - } - // (2.2) project onto left-coordinate: (0.5,1) - else if ( rSH->get_subset_index(vrt) == 2 ) - { - edge[0] = 0.5; edge[1] = 1.0; - number scalar = VecProd(project, edge); - - VecScale(project, edge, scalar); - ++counter2; - } - - // (2.3) project onto x-coordinate: (-0.5,1) - else if ( rSH->get_subset_index(vrt) == 1 ) - { - edge[0] = -0.5; edge[1] = 1.0; - number scalar = VecProd(project, edge); - - VecScale(project, edge, scalar); - ++counter3; - } - // (2.4) corner may not moved at all: (0,0) - else if ( rSH->get_subset_index(vrt) == 5 ) - { - project[0] = project[1] = 0.0; - ++counter4; - } - else - { - ++counter5; - continue; - } - - ///////////////////////////////////////////////// - // (3) write projected direction back to data 'u': - - // REMARK: this part of code is only reached for vertices on the boundary!!! - // --> see counter5: continue! - for (size_t cmp = 0; cmp < dim; ++cmp) - { - std::vector vInd; - if(dd->inner_dof_indices(vrt, cmp, vInd) != 1) - UG_THROW("1: error in inner_dof_indices operatio!\n"); - - DoFRef(u, vInd[0]) = project[cmp]; - ++counter6; - - - } - - } // end vertices-loop - - UG_LOG("counter1 = " << counter1 << "\n"); - UG_LOG("counter2 = " << counter2 << "\n"); - UG_LOG("counter3 = " << counter3 << "\n"); - UG_LOG("counter4 = " << counter4 << "\n"); - UG_LOG("counter5 = " << counter5 << "\n"); - UG_LOG("counter6 = " << counter6 << "\n"); - -} - -template -number MovingParticle:: -gradient_descent(const size_t n, const number functional, const number bound, const number scaleAlpha, vector_type& u, SmartPtr > spApproxSpace, SmartPtr > spMaster, const int topLevel) -{ - // set dummy value in order to pass second while-loop at least once: - number functionalNew = functional; - - UG_LOG("-----------> functionalNew = " << functionalNew << "\n"); - - if ( !(fabs(functionalNew) > bound) ) - UG_THROW("attention: first time this condition neads to be satisfied!\n"); - - //while ( fabs(functionalNew) > bound ) - if ( 1 ) - { - number alpha = scaleAlpha*compute_max_step_size(spApproxSpace, spMaster, topLevel); - UG_LOG("2 -----------> alpha = " << alpha << "\n"); - - bool iterate = true; - // while ( iterate ) - if ( 1 ) - { - ///////////////////////////////////////////////// - // loop vertices and update coordinates: - - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - DoFDistribution::traits::const_iterator iterBegin = dd->begin(); - DoFDistribution::traits::const_iterator iterEnd = dd->end(); - - // create MultiindexProjector - std::vector multInd; - - typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); - - // loop vertices - for(DoFDistribution::traits::const_iterator iter = iterBegin; iter != iterEnd; iter++) - { - // get vertex - Vertex* vrt = *iter; - MathVector position = aaPos[vrt]; - - for (size_t cmp = 0; cmp < dim; ++cmp) - { - std::vector vInd; - if(dd->inner_dof_indices(vrt, cmp, vInd) != 1) - UG_THROW("1: error in inner_dof_indices operatio!\n"); - - ///////////////////////////////////////////////// - // (1) get gradient = update direction: - MathVector update; - update[cmp] = DoFRef(u, vInd[0]); - - ///////////////////////////////////////////////// - // (2) update position coordinates due to - // gradient direction and step size alpha: - aaPos[vrt][cmp] = position[cmp] + alpha * update[cmp]; - - UG_LOG("aaPos[vrt][" << cmp << "]: " << aaPos[vrt][cmp] << "\n"); - - }// end cmp-loop - - - } // end vertices-loop - - UG_LOG("vorher -----------> functionalNew = " << functionalNew << "\n"); - - functionalNew = compute_functional(n, u, spApproxSpace, spMaster, topLevel); - alpha = 0.5*alpha; - - if ( functionalNew < 0.0 ) iterate = true; - else iterate = false; - - UG_LOG("nachher -----------> functionalNew = " << functionalNew << "\n"); - - - }// end while-loop - - // ToDo: wie Verschiebumg von aaPos wieder Rückgängig machen bzw. altes Gitter zwischenspeichern? => auf Clone updaten? - - }// end while-loop - -} - - -}// end namespace MovingParticle -} // end namespace ug - - - -#endif /* MEAN_ID_H_ */ diff --git a/incompressible/fv1/moving_particle/moving_particle.h b/incompressible/fv1/moving_particle/moving_particle.h index 0075f7b..ff0d141 100644 --- a/incompressible/fv1/moving_particle/moving_particle.h +++ b/incompressible/fv1/moving_particle/moving_particle.h @@ -38,7 +38,7 @@ namespace NavierStokes{ template < typename TDomain, typename TAlgebra> class MovingParticle - : public IMovingInterface + : public IImmersedInterface { public: /// world Dimension @@ -56,256 +56,201 @@ class MovingParticle typedef typename domain_traits::grid_base_object grid_base_object; MovingParticle(SmartPtr > ass, - SmartPtr > spMaster, - SmartPtr > cutElementHandler, - number fluidDensity, number fluidKinVisc); - - SmartPtr > get_BndCond() { return m_spInterfaceBndCond; } - - // SmartPtr > get_particles() { return m_spParticleHandlerGlobal->get_particles(); } - - void set_gravity(bool gravity, number gravityConst) { m_spInterfaceMapper->set_gravity(gravity, gravityConst); } - void set_repulsive_force(bool repForce, number forceValue) { m_spInterfaceMapper->set_repulsive_force(repForce, forceValue); } - void set_glowinski_repulsive_force(bool maxRepForce, number rho, number eps) { m_spInterfaceMapper->set_glowinski_repulsive_force(maxRepForce, rho, eps); } - void set_minimum_correction_force(bool EquiRepForce, number repulsiveDistance) { m_spInterfaceMapper->set_minimum_correction_force(EquiRepForce, repulsiveDistance); } - - void set_time_step(number dt) { m_spInterfaceMapper->set_time_step(dt); } - void set_volume_comp_mode(bool bVolumeCompMode) { m_spInterfaceMapper->set_volume_comp_mode(bVolumeCompMode); } - - void set_StdFV_assembling(bool bValue) { m_spInterfaceHandlerLocal->set_StdFV_assembling(bValue);} - bool StdFV_assembling() { return m_spInterfaceHandlerLocal->StdFV_assembling(); } - + SmartPtr > spMaster, + SmartPtr > cutElementHandler, + number fluidDensity, number fluidKinVisc); // destructor - ~MovingParticle(){}; + virtual ~MovingParticle(){}; + ////////////////////////////////////////////////////////////////////////////////////////// + // main methods + ////////////////////////////////////////////////////////////////////////////////////////// + + // general initialisation of set up data; + // most important: call of 'update_interface_data()' during init() of CutElementHandler + // --> marks the cut elements and interface vertices as + // INSIDE, OUTSIDE, CUT_BY_INTERFACE(element)/ON_INTERFACE(vertx) + // --> sets up the element lists CutElementHandlerParticle::m_vvvElemList, + // ::m_vvvElemListCut, ::m_vvvElemListOutside /// called via .lua: - void init(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel) - { -// UG_LOG("initialize on process " << pcl::ProcRank() << "\n"); - - m_spApproxSpace = spApproxSpace; - - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - - m_spParticleHandlerGlobal->template init(dd, baseLevel, topLevel); - // => update_multigrid_data() for all given levels - - // transfer direction: m_vvLinearVelocity/m_vvAngularVelocity ---> DoFRef(u, transInd) - // --> if particle velocities are FREE: m_vvLinearVelocity/m_vvAngularVelocity are initialized - // during ParticleProvider:adfd() with 0.0 => ok and INDEPENDENT of FREE or MOVING modus - update_particle_solution(u, topLevel); - } - - number MeanElementDiameter(TDomain& domain, int level); - void set_element_diameter(double val) { m_spInterfaceMapper->set_element_diameter(val); } - - ////////////////////////////////////////////////////////////////////////////////// - // ---> .lua: update(u, deltaT, u:grid_level()): update global indices (transInd...) - // => A. copy_solution(topLev) - // B. update(baseLev-topLev) - // C. update_solution(topLev) - ////////////////////////////////////////////////////////////////////////////////// - // write solution to nodes outside fluid with particle velocities - // --> call method vie .lua BEFORE 'solTimeSeries:push_discard_oldest(oldestSol, time)': - // => in case that outside nodes are inside AFTER update_prtCoords: NO solution defined here! - void update(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel, const number time, const number deltaT) - { - int topLev = spApproxSpace->num_levels()-1; - if ( topLev != topLevel ) - UG_THROW("NavierStokes::update: parameter 'topLevel' = " << topLevel << " != " - << topLev << "current top leven! \n"); - - // A. copy solution to data: DoFRef(u, transInd/rotInd) ---> m_vvLinearVelocity/m_vvAngularVelocity - // reverse direction done during 'NavierStokes::update_particle_solution()' - copy_particle_solution(u, topLevel); - - // B. synchronize particle data when everything in ParticleProvider is up to date. + void init(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, + const int topLevel); + + // mainly updates the coordinates of the particles for the next time step and updates the marker accordingly + // --> for that the solution in the DoFs for the particle motion needs to be + // (1) copied from DoFRef(u, ) into external storage: via call of 'store_particle_velocity()' + // (2) written back from storage to DoFRef(u, ): via call of 'write_particle_velocity()' + void update(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, + const int topLevel, const number time, const number deltaT); + #ifdef UG_PARALLEL - const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - m_spParticleHandlerGlobal->synchronize_particles(levIndex); + void pre_balancing_update(vector_type& u, SmartPtr > spApproxSpace, + const int baseLevel, const int topLevel, const number time, number deltaT); + + void post_balancing_update(vector_type& u, SmartPtr > spApproxSpace, + const int baseLevel, const int topLevel, const number time, number deltaT); #endif - // C. calculate new particle coordinates - m_spParticleHandlerGlobal->update_prtCoords(topLevel, deltaT); - - // D. fill particle nodes with their real solution - // --> FIRST copy_particle_solution() necessary, since eventually during - // fill extraDoF-nodes will be overwriten - fill_particle_solution(u, topLevel, time); - - // E. update data => new node for (u, transInd) ! - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - m_spParticleHandlerGlobal->template init(dd, baseLevel, topLevel); - - // F. update solution from data: m_vSolTransDoFRef(u, transInd/rotInd) - // transfer direction: m_vvLinearVelocity/m_vvAngularVelocity ---> DoFRef(u, transInd) - update_particle_solution(u, topLevel); - - // reset volume: - m_spInterfaceMapper->reset_volume(); - } - - void get_velocity(MathVector& transSol, MathVector& rotSol, const vector_type& u, const int topLevel, number deltaT, const size_t prtIndex); -#ifdef UG_PARALLEL - void pre_balancing_update(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel, const number time, number deltaT) - { - int topLev = spApproxSpace->num_levels()-1; - if ( topLev != topLevel ) - UG_THROW("NavierStokes::update: parameter 'topLevel' = " << topLevel << " != " - << topLev << "current top leven! \n"); - - const char* filename = "update_times"; - std::string name(filename); - char ext[50]; - sprintf(ext, "_%d.txt", pcl::ProcRank()); - //sprintf(ext, ".txt"); - name.append(ext); - FILE* outputFile = fopen(name.c_str(), "a"); - - std::clock_t begin = std::clock(); - // A. copy solution to data: DoFRef(u, transInd) ---> m_vSolTrans - // reverse direction done during 'NavierStokes::update_particle_solution()' - copy_particle_solution(u, topLevel); - std::clock_t end = std::clock(); - fprintf(outputFile,"copy_particle_solution %f", double(end - begin) / CLOCKS_PER_SEC); - - begin = std::clock(); - - // C. calculate new particle coordinates - m_spParticleHandlerGlobal->update_prtCoords(topLevel, deltaT); - end = std::clock(); - fprintf(outputFile,"update_prtCoords %f", double(end - begin) / CLOCKS_PER_SEC); - - begin = std::clock(); - // B. synchronize particle data when everything in ParticleProvider is up to date. - - const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - m_spParticleHandlerGlobal->synchronize_particles(levIndex); - - end = std::clock(); - fprintf(outputFile,"synchronize_particles %f", double(end - begin) / CLOCKS_PER_SEC); - - begin = std::clock(); - - // D. fill particle nodes with their real solution - // --> FIRST copy_particle_solution() necessary, since eventually during - // fill extraDoF-nodes will be overwriten - fill_particle_solution(u, topLevel, time); - end = std::clock(); - fprintf(outputFile,"fill_particle_solution %f", double(end - begin) / CLOCKS_PER_SEC); - - fclose(outputFile); - - } - void post_balancing_update(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel, const number time, number deltaT) - { - // E. update data => new node for (u, transInd) ! - ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - m_spParticleHandlerGlobal->template init(dd, baseLevel, topLevel); - - // F. update solution from data: m_vSolTransDoFRef(u, transInd) - // transfer direction: m_vSolTrans ---> DoFRef(u, transInd) - update_particle_solution(u, topLevel); - - // reset volume: - m_spInterfaceMapper->reset_volume(); - } -#endif - - void compute_gradient_local_max(vector_type& sol, vector_type& grad,SmartPtr > spApproxSpace, const int topLevel); + ////////////////////////////////////////////////////////////////////////////////////////// + // helper methods for init() and update() + ////////////////////////////////////////////////////////////////////////////////////////// + + // transfer direction: + // DoFRef(u, transInd) ---> ParticleProvider::m_vvLinearVelocity/m_vvAngularVelocity + void store_particle_velocity(vector_type& u, const int topLevel); - /// call of the method via lua to set the real velocity values within the particle domain + // transfer direction: + // ParticleProvider::m_vvLinearVelocity/m_vvAngularVelocity ---> DoFRef(u, transInd) + void write_particle_velocity(vector_type& u, const int topLevel); + + ////////////////////////////////////////////////////////////////////////////////////////// + // write solution to 'FREED' nodes, i.e. nodes which were inside particle in the last + // time step and are outside the particle (i.e. freed) in the current time step + // --> call method via .lua BEFORE 'solTimeSeries:push_discard_oldest(oldestSol, time)': + // (if not: in case that outside nodes are inside the domain AFTER updating the + // particle coordinates, NO solution will be defined here!) + void fill_freed_nodes(vector_type& u, const int topLevel, const number time); + + ////////////////////////////////////////////////////////////////////////////////////////// + // helper methods for init() and update() + ////////////////////////////////////////////////////////////////////////////////////////// + + // currently not used + void compute_gradient_local_max(vector_type& sol, vector_type& grad, + SmartPtr > spApproxSpace, const int topLevel); + + /// writes the physical velocity values to the nodes lying in the particle domain + // (call via lua for visualisation purposes) void adjust_global_solution(vector_type& u, const int topLevel); - void fill_particle_solution(vector_type& u, const int topLevel, const number time); - - /// transfer direction: DoFRef(u, transInd) ---> m_vSolTrans - void copy_particle_solution(vector_type& u, const int topLevel); - /// transfer direction: m_vSolTrans ---> DoFRef(u, transInd) - void update_particle_solution(vector_type& u, const int topLevel); - - void initialize_threshold(TDomain& domain, const int baseLevel, const int topLevel); + ////////////////////////////////////////////////////////////////////////////////////////// + /// methods for setting up the forces for collision (by Jonas Simon, see Master Thesis) + ////////////////////////////////////////////////////////////////////////////////////////// + + void set_repulsive_force(bool repForce, number forceValue) + { m_spInterfaceMapper->set_repulsive_force(repForce, forceValue); } + void set_glowinski_repulsive_force(bool maxRepForce, number rho, number eps) + { m_spInterfaceMapper->set_glowinski_repulsive_force(maxRepForce, rho, eps); } + void set_minimum_correction_force(bool EquiRepForce, number repulsiveDistance) + { m_spInterfaceMapper->set_minimum_correction_force(EquiRepForce, repulsiveDistance); } + + bool mark_collision_area(SmartPtr refiner, int level); + double estimate_repulsive_force_parameters(vector_type& u, int topLevel, double MaxElemDiameter, double deltaT); + void set_forceLog(bool val) { m_spInterfaceMapper->set_forceLog(val); } + void set_mpi_routine(int val){ m_spCutElementHandler->set_mpi_routine(val); } + + + ////////////////////////////////////////////////////////////////////////////////////////// + // some getter and setter methods + ////////////////////////////////////////////////////////////////////////////////////////// - /// checks if grid data is updated and returns 'levIndex'-pair for 'gridLevel' in 'm_Map' - int get_Index(const GridLevel& gridLevel) - { - ConstSmartPtr dd = m_spApproxSpace->dof_distribution(gridLevel); + SmartPtr > get_BndCond() { return m_spInterfaceBndCond; } - const int levIndex = m_spParticleHandlerGlobal->get_Index(gridLevel, dd); + /// checks if grid data is updated and returns the 'levIndex' of the 'gridLevel' via access to 'CutElementHandlerBase::m_Map' + int get_Index(const GridLevel& gridLevel); + + /// returns true, if computation is time dependent + bool is_time_dependent() { return m_spInterfaceMapper->is_time_dependent();} + - return levIndex; - } + ////////////////////////////////////////////////////////////////////////////////////////// + /// lua-methods for set up: + ////////////////////////////////////////////////////////////////////////////////////////// + + // the 'threshold' defines the bandwidth around the immersed interface, in which a node + // counts as 'OUTSIDE' or 'ON_INTERFACE' during call of 'CutElementHandler::is_outside()' + // and 'CutElementHandler::is_nearInterface() + void initialize_threshold(TDomain& domain, const int baseLevel, const int topLevel); + void set_threshold(size_t level, const number threshold) + { m_spCutElementHandler->set_threshold(level, threshold); } + number MeanElementDiameter(TDomain& domain, int level); + + // If StdFV-assembling is ON, NO new 'vCornerCoords' will be computed on the cut elements. + // The original nodes ACCROSS the interface (ON the euclidian mesh) will be chosen for the + // computation of the solution of the interface + // ==> the standard shape functions w.r.t. the non-conforming mesh will be used + // (similar as in common 'ficticious domain' methods) + // ==> the shape functions will NOT be 1 ON the interface and the gradient will NOT + // point normal to the interface + void set_StdFV_assembling(bool bValue) { m_spInterfaceHandlerLocal->set_StdFV_assembling(bValue);} + bool StdFV_assembling() { return m_spInterfaceHandlerLocal->StdFV_assembling(); } + + // setting and getting flag for printing of cut-element data into file: + void set_print_cutElemData(bool bValue) { m_spInterfaceHandlerLocal->set_print_cutElemData(bValue); } - // void clear_solution(SmartPtr > vSol, const GridLevel& topGrid); - void clear_solution(vector_type& u, const int topLevel); - /// see ParticleConstraint::adjust_solution() -// void update_solution(SmartPtr > vSol, const GridLevel& topGrid); + void set_element_diameter(double val) { m_spInterfaceMapper->set_element_diameter(val); } + void set_volume_comp_mode(bool bVolumeCompMode) { m_spInterfaceMapper->set_volume_comp_mode(bVolumeCompMode); } + void set_gravity(bool gravity, number gravityConst) { m_spInterfaceMapper->set_gravity(gravity, gravityConst); } + void set_time_step(number dt) { m_spInterfaceMapper->set_time_step(dt); } - bool is_time_dependent() { return m_spInterfaceMapper->is_time_dependent();} + // writes the velocity of the prtIndex-th particle into 'transSol' and 'rotSol' for further computatino or output + void get_velocity(MathVector& transSol, MathVector& rotSol, const vector_type& u, + const int topLevel, number deltaT, const size_t prtIndex); + -number compute_functional_fixed(const size_t n, vector_type& u, SmartPtr > spApproxSpace, SmartPtr > spMaster, const int topLevel); + ////////////////////////////////////////////////////////////////////////////////////////// + // lua-methods for output + ////////////////////////////////////////////////////////////////////////////////////////// -number compute_functional_combined(const size_t n, vector_type& u, SmartPtr > spApproxSpace, SmartPtr > spMaster, const int topLevel); + /// writing data to file; called via .lua + void print_velocity(const vector_type& u, const int topLevel, number time, const char* filename); -number compute_functional(const size_t n, vector_type& u, SmartPtr > spApproxSpace, SmartPtr > spMaster, const int topLevel); -number compute_functional_all(const size_t n, vector_type& u, SmartPtr > spApproxSpace, SmartPtr > spMaster, const int topLevel); + // writes the pressure on the front and back of the cylinder and the delta of it into a file + void print_deltaP(const vector_type& u, const int topLevel); -number compute_max_step_size(SmartPtr > spApproxSpace, - SmartPtr > spMaster, const int topLevel); -number gradient_descent(const size_t n, const number functional, const number bound, const number scaleAlpha, vector_type& u, SmartPtr > - spApproxSpace, SmartPtr > spMaster, const int topLevel); -void project_directions(const number functional, vector_type& u, SmartPtr > spApproxSpace, - SmartPtr > spMaster, const int topLevel); -void rescale_directions(const number functional, vector_type& u, SmartPtr > spApproxSpace, - SmartPtr > spMaster, const int topLevel); - + // writes the pressure value along the circular interface in grid nodes into file + void print_pressure_nodal(const vector_type& u, const int topLevel); - /// helper functions for compute_error_on_circle() - void interpolate_point(ConstSmartPtr dd, const vector_type& u, - const MathVector& evalPos, MathVector& interpolation); -// void compute_error_on_circle(const vector_type& u, const int topLevel, number radius); - - void print_deltaP(const vector_type& u, const int topLevel); - void print_pressure(const vector_type& u, const int topLevel); - void print_pressure_nodal(const vector_type& u, const int topLevel); - - /// writing data to file; called via .lua - void print_velocity(const vector_type& u, const int topLevel, number time, const char* filename); - // void print_velocity_many_particles(const vector_type& u, const int topLevel, number time, const char* filename); + // writes the pressure value along the circular interface for equidistant angle teta into file + void print_pressure_teta(const vector_type& u, const int topLevel); - bool mark_collision_area(SmartPtr refiner, int level); - double estimate_repulsive_force_parameters(vector_type& u, int topLevel, double MaxElemDiameter, double deltaT); - void set_forceLog(bool val) { - m_spInterfaceMapper->set_forceLog(val); - } + // interpolates the value at a non-grid point (used for the computation of deltaP in 'print_deltaP()' + void interpolate_point(ConstSmartPtr dd, const vector_type& u, + const MathVector& evalPos, MathVector& interpolation); - void set_mpi_routine(int val){ - m_spParticleHandlerGlobal->set_mpi_routine(val); - } + // returns the number of DoFs on the original grid + size_t get_numCutElements(const int gridlevel, const size_t prtIndex) + { + ConstSmartPtr dd = m_spApproxSpace->dof_distribution(GridLevel(gridlevel, GridLevel::LEVEL)); + const int levIndex = m_spCutElementHandler->get_Index(gridlevel, dd); + + return m_spCutElementHandler->get_numCutElements(levIndex, prtIndex); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////// + // class member + /////////////////////////////////////////////////////////////////////////////////////////////////////////// + private: - // new member - SmartPtr > m_spParticleHandlerGlobal; - SmartPtr > m_spInterfaceHandlerLocal; + // new member + SmartPtr > m_spCutElementHandler; // member from base class - SmartPtr > m_spInterfaceMapper; // contains member of class 'IInterfaceHandlerLocal' - SmartPtr > m_spInterfaceBndCond; // contains member of class 'IInterfaceHandlerLocal' + SmartPtr > m_spInterfaceHandlerLocal; // contains class member + // 'CutElementHandler_FlatTop' + SmartPtr > m_spInterfaceMapper; // contains class member + // 'IInterfaceHandlerLocal' + SmartPtr > m_spInterfaceBndCond; // contains class member + // 'IInterfaceHandlerLocal' /// current ApproxSpace SmartPtr > m_spApproxSpace; -}; +}; // end class MovingParticle + + #ifdef UG_PARALLEL - template - class ParticleUnificator : public parmetis::IUnificator::base_obj_type> - { +template +class ParticleUnificator : public parmetis::IUnificator::base_obj_type> +{ + public: typedef typename GeomObjBaseTypeByDim::base_obj_type elem_t; typedef typename elem_t::side side_t; @@ -327,7 +272,7 @@ void rescale_directions(const number functional, vector_type& u, SmartPtr spDom) - : m_spMG(spDom->grid().operator->()) + : m_spMG(spDom->grid()) { // get position attachment m_aPos = GetDefaultPositionAttachment(); @@ -635,7 +580,8 @@ void rescale_directions(const number functional, vector_type& u, SmartPtr > > m_vParticleCoord; - }; + +}; // end class ParticleUnificator #endif @@ -645,7 +591,6 @@ void rescale_directions(const number functional, vector_type& u, SmartPtr MovingParticle::MovingParticle( SmartPtr > ass, - SmartPtr > spMaster, - SmartPtr > cutElementHandler, - number fluidDensity, number fluidKinVisc) : - m_spParticleHandlerGlobal(cutElementHandler), + SmartPtr > spMaster, + SmartPtr > cutElementHandler, + number fluidDensity, number fluidKinVisc) +: m_spCutElementHandler(cutElementHandler), m_spInterfaceHandlerLocal( new InterfaceHandlerLocalParticle(cutElementHandler, fluidDensity, fluidKinVisc) ), m_spInterfaceMapper( @@ -37,7 +37,7 @@ MovingParticle::MovingParticle( if (cutElementHandler->num_particles() == 0) UG_THROW("MovingParticle::Constructor(): no particles initializen in 'cutElementHandler\n"); - // initialize singleton and set local handler +// initialize singleton and set local handler typedef DimFV1FTGeometry > TFVGeom; TFVGeom& geo = GeomProvider::get(LFEID(LFEID::LAGRANGE, dim, 1), 1); geo.set_interface_handler(m_spInterfaceHandlerLocal); @@ -45,33 +45,93 @@ MovingParticle::MovingParticle( // initialize mapper within domainDisc: SmartPtr > assAdapt = ass->ass_tuner(); assAdapt->set_mapping(m_spInterfaceMapper.get()); - assAdapt->enable_modify_solution(true); - - // => assTuner->modify_LocSol() = mapper->modify_LocSol() - // see: ass_tuner.h: 114 - - // ToDo: reconstruct modify_LocSol: ??? - // assAdapt->set_local_modifier(); +// needs to be enabled, in order to call 'spAssTuner->modify_LocalData()' during element disc assembling + assAdapt->enable_modify_solution(true); } -/* - template - void MovingParticle:: - clear_solution(SmartPtr > vSol, const GridLevel& topGrid) - { - //approxSpace->dof_distribution(GridLevel(GridLevel::TOP, GridLevel::SURFACE)), time); - - } - */ - + +template +void MovingParticle:: +init(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, + const int topLevel) +{ + // get data + m_spApproxSpace = spApproxSpace; + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + +// call of 'CutElementHadlerFT::update_interface_data(): for all given levels + m_spCutElementHandler->template init(dd, baseLevel, topLevel); + +// transfer particle velocity: +// FROM m_vvLinearVelocity/m_vvAngularVelocity (initialized during 'ParticleProvider::add()' +// TO DoFRef(u, transInd)/DoFRef(u, rotInd) (for the later solution process) + write_particle_velocity(u, topLevel); + +} + + +template +void MovingParticle:: +update(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, + const int topLevel, const number time, const number deltaT) +{ + int topLev = spApproxSpace->num_levels()-1; + if ( topLev != topLevel ) + UG_THROW("NavierStokes::update: parameter 'topLevel' = " << topLevel << " != " + << topLev << "current top leven! \n"); + + // A. copy particle velocity to data: DoFRef(u, transInd/rotInd) ---> m_vvLinearVelocity/m_vvAngularVelocity + // reverse direction done during 'NavierStokes::write_particle_velocity()' --> see F. + store_particle_velocity(u, topLevel); + +#ifdef UG_PARALLEL + // B. synchronize particle data when everything in ParticleProvider is up to date. + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + m_spCutElementHandler->synchronize_particles(levIndex); +#endif + + // C. calculate new particle coordinates + m_spCutElementHandler->update_prtCoords(topLevel, deltaT); + + // D. write solution to 'FREED' nodes, i.e. nodes which were inside particle in the last + // time step and are outside the particle (i.e. freed) in the current time step + // --> needs to be called AFTER 'update_prtCoords(), since being inside particle refers + // already to new coordinates + // --> needs to be called BEFORE 'm_spCutElementHandler->template init(), since being + // inside particle refers to OLD BoolMarker + fill_freed_nodes(u, topLevel, time); + + // E. update marker and global indices => new location for (u, transInd), (u, rotInd) ! + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + m_spCutElementHandler->template init(dd, baseLevel, topLevel); + + // F. write solution into new location of global indices 'transInd' and 'rotInd': + // transfer direction: m_vvLinearVelocity/m_vvAngularVelocity ---> DoFRef(u, transInd)/DoFRef(u, rotInd) + write_particle_velocity(u, topLevel); + + // reset volume: + m_spInterfaceMapper->reset_volume(); +} + template -number MovingParticle::MeanElementDiameter(TDomain& domain, - int level) { +int MovingParticle:: +get_Index(const GridLevel& gridLevel) +{ + ConstSmartPtr dd = m_spApproxSpace->dof_distribution(gridLevel); + + const int levIndex = m_spCutElementHandler->get_Index(gridLevel, dd); + + return levIndex; +} + +template +number MovingParticle:: +MeanElementDiameter(TDomain& domain, int level) +{ + typedef typename domain_traits::grid_base_object TElem; - - //typedef typename std::vector::iterator ListIter; typedef typename geometry_traits::iterator ListIter; ListIter iter = domain.grid()->template begin(level); @@ -85,8 +145,7 @@ number MovingParticle::MeanElementDiameter(TDomain& domain, numIter++; } - mean = mean / numIter; - UG_LOG("mean = " << std::sqrt(mean) << "\n"); + mean = mean / numIter; #ifdef UG_PARALLEL // share value between all procs @@ -96,21 +155,18 @@ number MovingParticle::MeanElementDiameter(TDomain& domain, mean = com.allreduce(mean, PCL_RO_MIN); #endif - UG_LOG("nach com.allreduce: mean = " << std::sqrt(mean) << "\n"); + UG_LOG("nach com.allreduce: mean = " << std::sqrt(mean) << "\n"); return std::sqrt(mean); } template -void MovingParticle::initialize_threshold(TDomain& domain, - const int baseLevel, const int topLevel) { - UG_LOG("----------------- START initialize_threshold() ---------------- \n"); - +void MovingParticle:: +initialize_threshold(TDomain& domain, const int baseLevel, const int topLevel) +{ if (baseLevel < 0) - UG_THROW( - "initialize_threshold(): no cast of baselevel from 'int' tp 'size_t' possible! \n"); + UG_THROW("initialize_threshold(): no cast of baselevel from 'int' tp 'size_t' possible! \n"); if (topLevel < 0) - UG_THROW( - "initialize_threshold(): no cast of toplevel from 'int' tp 'size_t' possible! \n"); + UG_THROW("initialize_threshold(): no cast of toplevel from 'int' tp 'size_t' possible! \n"); typedef typename domain_traits::grid_base_object TElem; @@ -123,188 +179,175 @@ void MovingParticle::initialize_threshold(TDomain& domain, UG_LOG("threshold_max = " << maxLength*maxLength << "\n"); UG_LOG("threshold_mean = " << meanLength*meanLength << "\n"); - m_spParticleHandlerGlobal->set_threshold(lev, meanLength * meanLength); - //m_spParticleHandlerGlobal->set_threshold(lev, 0.003); + set_threshold(lev, meanLength * meanLength); } UG_LOG("----------------- END initialize_threshold() ---------------- \n"); -} - -template -void MovingParticle:: -get_velocity(MathVector& transSol, MathVector& rotSol, const vector_type& u, const int topLevel, number deltaT, const size_t prtIndex) -{ - UG_LOG("MovingParticle::print_velocity(): Start: \n"); - - size_t numPrt = m_spParticleHandlerGlobal->num_particles(); - - // if ( numPrt > 2 ) - // UG_THROW("Particle:output_velocity: VORSICHT, output nicht implementiert fuer mehr als 2 particle! -> m_bShared[][] ist Problem! ... Exit! \n"); - - const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - - -#ifdef UG_PARALLEL - std::vector ElemList = m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][prtIndex]; - UG_LOG("1 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << "\n"); - if (ElemList.size() == 0) { - UG_LOG("2 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); - return; - } -#endif - // get multiindices for translation and rotation of particle - std::vector < DoFIndex > transInd = m_spParticleHandlerGlobal->get_transInd(levIndex, prtIndex); - std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd(levIndex, prtIndex); - - - for ( int d = 0; d < dim; ++d ) - { - transSol[d] = DoFRef(u, transInd[d]); - rotSol[d] = DoFRef(u, rotInd[d]); - UG_LOG("in get_velocity: transSol: " << transSol[d] << "\t rotSol: " << rotSol[d] << "\n"); - } - - - } // transfer direction: DoFRef(u, transInd) ---> m_vvLinearVelocity/m_vvAngularVelocity template -void MovingParticle::copy_particle_solution(vector_type& u, - const int topLevel) { +void MovingParticle:: +store_particle_velocity(vector_type& u, const int topLevel) +{ + bool output = false; const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + for (size_t p = 0; p < m_spCutElementHandler->num_particles(); ++p) { #ifdef UG_PARALLEL - std::vector ElemList = - m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; - UG_LOG( - "1 MovingParticle::copy_solution: ElemList.size(): " << ElemList.size() << "\n"); + // use size of member 'CutElementHandler_FlatTop::m_vvvElemListCut' in order + // to indicate, whether a particle lies on a processor or not + std::vector ElemList = m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; + UG_LOG("1 MovingParticle::store_particle_velocity: ElemList.size(): " << ElemList.size() << "\n"); if (ElemList.size() == 0) { - UG_LOG( - "2 MovingParticle::copy_solution: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + UG_LOG("2 MovingParticle::store_particle_velocity: ElemList.size(): " + << ElemList.size() << " => skip assembling! \n"); continue; } #endif -#ifdef UG_DEBUG - UG_LOG( - "copy_solution(): VORHER transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); - UG_LOG( - "copy_solution(): VORHER transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); - UG_LOG( - "copy_solution(): VORHER rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); - UG_LOG( - "copy_solution(): VORHER rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); -#endif - // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) + if ( output ){ + UG_LOG("copy_solution(): VORHER transSol(0) = " << m_spCutElementHandler->get_transSol(p,0) << "\n"); + UG_LOG("copy_solution(): VORHER transSol(1) = " << m_spCutElementHandler->get_transSol(p, 1) << "\n"); + UG_LOG("copy_solution(): VORHER rotSol(0) = " << m_spCutElementHandler->get_rotSol(p,0) << "\n"); + UG_LOG("copy_solution(): VORHER rot1Sol(1) = " << m_spCutElementHandler->get_rotSol(p, 1) << "\n"); + } + + // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) std::vector < DoFIndex > transInd = - m_spParticleHandlerGlobal->get_transInd(levIndex, p); - std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd( - levIndex, p); + m_spCutElementHandler->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = + m_spCutElementHandler->get_rotInd(levIndex, p); UG_LOG(" transInd(0) = " << transInd[0] << "\n"); UG_LOG(" rotInd(0) = " << rotInd[0] << "\n"); - for (int d = 0; d < dim; ++d) { + // finally: write solution from m_vvLinearVelocity/m_vvAngularVelocity to DoFRef and set + // solution in DoFRef to zero + for (int d = 0; d < dim; ++d) + { number solution = DoFRef(u, transInd[d]); - m_spParticleHandlerGlobal->set_extraSolTrans(solution, p, 0, d); + m_spCutElementHandler->set_extraSolTrans(solution, p, 0, d); DoFRef(u, transInd[d]) = 0.0; solution = DoFRef(u, rotInd[d]); - m_spParticleHandlerGlobal->set_extraSolRot(solution, p, 0, d); + m_spCutElementHandler->set_extraSolRot(solution, p, 0, d); DoFRef(u, rotInd[d]) = 0.0; } -#ifdef UG_DEBUG - UG_LOG( - "copy_solution(): NACHHER transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); - UG_LOG( - "copy_solution(): NACHHER transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); - UG_LOG( - "copy_solution(): NACHHER rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); - UG_LOG( - "copy_solution(): NACHHER rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); -#endif + + if ( output ){ + UG_LOG("copy_solution(): NACHHER transSol(0) = " << m_spCutElementHandler->get_transSol(p,0) << "\n"); + UG_LOG("copy_solution(): NACHHER transSol(1) = " << m_spCutElementHandler->get_transSol(p, 1) << "\n"); + UG_LOG("copy_solution(): NACHHER rotSol(0) = " << m_spCutElementHandler->get_rotSol(p,0) << "\n"); + UG_LOG("copy_solution(): NACHHER rot1Sol(1) = " << m_spCutElementHandler->get_rotSol(p, 1) << "\n"); + } + } // end particle loop } + + +template +void MovingParticle:: +get_velocity(MathVector& transSol, MathVector& rotSol, const vector_type& u, + const int topLevel, number deltaT, const size_t prtIndex) +{ + // get data + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + +#ifdef UG_PARALLEL + // use size of member 'CutElementHandler_FlatTop::m_vvvElemListCut' in order + // to indicate, whether a particle lies on a processor or not + std::vector ElemList = m_spCutElementHandler->m_vvvElemListCut[levIndex][prtIndex]; + UG_LOG("1 MovingParticle::get_velocity: ElemList.size(): " << ElemList.size() << "\n"); + if (ElemList.size() == 0) { + UG_LOG("2 MovingParticle::get_velocity: ElemList.size(): " << ElemList.size() << + " => skip assembling! \n"); + return; + } +#endif + // get multiindices for translation and rotation of particle + std::vector < DoFIndex > transInd = m_spCutElementHandler->get_transInd(levIndex, prtIndex); + std::vector < DoFIndex > rotInd = m_spCutElementHandler->get_rotInd(levIndex, prtIndex); + + + for ( int d = 0; d < dim; ++d ) + { + transSol[d] = DoFRef(u, transInd[d]); + rotSol[d] = DoFRef(u, rotInd[d]); + } + +} + template -void MovingParticle::compute_gradient_local_max( - vector_type& sol, vector_type& grad, - SmartPtr > spApproxSpace, - const int topLevel) { +void MovingParticle:: +compute_gradient_local_max(vector_type& sol, vector_type& grad, + SmartPtr > spApproxSpace, const int topLevel) +{ // get data typedef typename domain_traits::grid_base_object grid_base_object; - typename DoFDistribution::traits::const_iterator iter, - iterEnd; + typename DoFDistribution::traits::const_iterator iter, iterEnd; ConstSmartPtr dd = spApproxSpace->dof_distribution( GridLevel(topLevel, GridLevel::LEVEL)); typename TDomain::position_accessor_type aaPos = - m_spParticleHandlerGlobal->m_aaPos; + m_spCutElementHandler->m_aaPos; iter = dd->template begin(); iterEnd = dd->template end(); - // loop elements in order to compute the volume and set rhs: +// loop elements in order to compute the volume and set rhs: for (; iter != iterEnd; iter++) { - // get element + // get element grid_base_object* elem = *iter; - if (m_spParticleHandlerGlobal->m_spOutsideMarker->is_marked(elem)) + if (m_spCutElementHandler->m_spOutsideMarker->is_marked(elem)) continue; std::vector < DoFIndex > vInd1; std::vector < DoFIndex > vInd2; std::vector vEdges; - CollectEdgesSorted(vEdges, *m_spParticleHandlerGlobal->m_spMG, elem); + CollectEdgesSorted(vEdges, *m_spCutElementHandler->m_spMG, elem); - if (m_spParticleHandlerGlobal->m_spCutMarker->is_marked(elem)) { + if (m_spCutElementHandler->m_spCutMarker->is_marked(elem)) { for (size_t e = 0; e < vEdges.size(); ++e) { Edge* edge = vEdges[e]; std::vector vVertexEdge; - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, + CollectVertices(vVertexEdge, *m_spCutElementHandler->m_spMG, edge); if (vVertexEdge.size() != 2) - UG_THROW( - "error in collecting vertices associated to an edge!....EXIT!...\n"); + UG_THROW("error in collecting vertices associated to an edge!...EXIT!...\n"); Vertex* vrt1 = vVertexEdge[0]; Vertex* vrt2 = vVertexEdge[1]; - // no gradient needs to be computed on outside edges: - if (m_spInterfaceHandlerLocal->is_FTVertex(vrt1) - && m_spInterfaceHandlerLocal->is_FTVertex(vrt2)) + // no gradient needs to be computed on outside edges: + if (m_spInterfaceHandlerLocal->is_onInterfaceVertex(vrt1) + && m_spInterfaceHandlerLocal->is_onInterfaceVertex(vrt2)) continue; if (dd->inner_dof_indices(vrt1, dim, vInd1) != 1) - UG_THROW( - "MovingParticle::compute_gradient(): Only one index expected."); + UG_THROW("MovingParticle::compute_gradient(): Only one index expected."); if (dd->inner_dof_indices(vrt2, dim, vInd2) != 1) - UG_THROW( - "MovingParticle::compute_gradient(): Only one index expected."); - - // compute local gradient along the edge - // UG_LOG("DoFRef(sol,vInd1[0]): " << DoFRef(sol,vInd1[0]) << "\n"); - // UG_LOG("DoFRef(sol,vInd2[0]): " << DoFRef(sol,vInd2[0]) << "\n"); + UG_THROW("MovingParticle::compute_gradient(): Only one index expected."); - number grad_edge = fabs( - DoFRef(sol, vInd1[0]) - DoFRef(sol, vInd2[0])); + // compute local gradient along the edge + number grad_edge = fabs(DoFRef(sol, vInd1[0]) - DoFRef(sol, vInd2[0])); number edgeLength = VecDistance(aaPos[vrt1], aaPos[vrt2]); - if (!m_spInterfaceHandlerLocal->is_FTVertex(vrt1) - && !m_spInterfaceHandlerLocal->is_FTVertex(vrt2)) { // nothing has to be adapted! - } else if (m_spInterfaceHandlerLocal->is_FTVertex(vrt1)) { - if (m_spInterfaceHandlerLocal->is_FTVertex(vrt2)) + if (!m_spInterfaceHandlerLocal->is_onInterfaceVertex(vrt1) + && !m_spInterfaceHandlerLocal->is_onInterfaceVertex(vrt2)) { // nothing has to be adapted! + } else if (m_spInterfaceHandlerLocal->is_onInterfaceVertex(vrt1)) { + if (m_spInterfaceHandlerLocal->is_onInterfaceVertex(vrt2)) UG_THROW("hmmm...wrong in 'compute_gradient()'...\n"); - // compute intersectionPoint: + // compute intersectionPoint: MathVector intersectionPnt; if (m_spInterfaceHandlerLocal->is_nearInterfaceVertex(vrt1)) VecCopy(intersectionPnt, aaPos[vrt1], 0.0); @@ -312,36 +355,34 @@ void MovingParticle::compute_gradient_local_max( m_spInterfaceHandlerLocal->get_intersection_point( intersectionPnt, vrt2, vrt1); - // compute edgeLength: + // compute edgeLength: edgeLength = VecDistance(aaPos[vrt2], intersectionPnt); - } else if (m_spInterfaceHandlerLocal->is_FTVertex(vrt2)) { - if (m_spInterfaceHandlerLocal->is_FTVertex(vrt1)) + } else if (m_spInterfaceHandlerLocal->is_onInterfaceVertex(vrt2)) { + if (m_spInterfaceHandlerLocal->is_onInterfaceVertex(vrt1)) UG_THROW("hmmm...wrong in 'compute_gradient()'...\n"); - // compute intersectionPoint: + // compute intersectionPoint: MathVector intersectionPnt; if (m_spInterfaceHandlerLocal->is_nearInterfaceVertex(vrt2)) VecCopy(intersectionPnt, aaPos[vrt2], 0.0); else m_spInterfaceHandlerLocal->get_intersection_point( intersectionPnt, vrt1, vrt2); - // compute edgeLength: + // compute edgeLength: edgeLength = VecDistance(aaPos[vrt1], intersectionPnt); } grad_edge = grad_edge / edgeLength; // set local maximum over all gradients along the edge to a given vertex - DoFRef(grad, vInd1[0]) = std::max(DoFRef(grad, vInd1[0]), - grad_edge); - DoFRef(grad, vInd2[0]) = std::max(DoFRef(grad, vInd2[0]), - grad_edge); + DoFRef(grad, vInd1[0]) = std::max(DoFRef(grad, vInd1[0]), grad_edge); + DoFRef(grad, vInd2[0]) = std::max(DoFRef(grad, vInd2[0]), grad_edge); } // end edge-loop } else { for (size_t e = 0; e < vEdges.size(); ++e) { Edge* edge = vEdges[e]; std::vector vVertexEdge; - CollectVertices(vVertexEdge, *m_spParticleHandlerGlobal->m_spMG, + CollectVertices(vVertexEdge, *m_spCutElementHandler->m_spMG, edge); if (vVertexEdge.size() != 2) UG_THROW( @@ -350,11 +391,9 @@ void MovingParticle::compute_gradient_local_max( Vertex* vrt1 = vVertexEdge[0]; Vertex* vrt2 = vVertexEdge[1]; if (dd->inner_dof_indices(vrt1, dim, vInd1) != 1) - UG_THROW( - "MovingParticle::compute_gradient(): Only one index expected."); + UG_THROW("MovingParticle::compute_gradient(): Only one index expected."); if (dd->inner_dof_indices(vrt2, dim, vInd2) != 1) - UG_THROW( - "MovingParticle::compute_gradient(): Only one index expected."); + UG_THROW("MovingParticle::compute_gradient(): Only one index expected."); // compute local gradient along the edge number edgeLength = VecDistance(aaPos[vrt1], aaPos[vrt2]); @@ -363,10 +402,8 @@ void MovingParticle::compute_gradient_local_max( grad_edge = grad_edge / edgeLength; // set local maximum over all gradients along the edge to a given vertex - DoFRef(grad, vInd1[0]) = std::max(DoFRef(grad, vInd1[0]), - grad_edge); - DoFRef(grad, vInd2[0]) = std::max(DoFRef(grad, vInd2[0]), - grad_edge); + DoFRef(grad, vInd1[0]) = std::max(DoFRef(grad, vInd1[0]), grad_edge); + DoFRef(grad, vInd2[0]) = std::max(DoFRef(grad, vInd2[0]), grad_edge); } // end edge-loop @@ -377,70 +414,53 @@ void MovingParticle::compute_gradient_local_max( } template -void MovingParticle::adjust_global_solution(vector_type& u, - const int topLevel) { - const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); +void MovingParticle:: +adjust_global_solution(vector_type& u, const int topLevel) +{ +// get data + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { +// loop all particles + for (size_t p = 0; p < m_spCutElementHandler->num_particles(); ++p) + { #ifdef UG_PARALLEL - std::vector ElemList = - m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; - UG_LOG( - "1 MovingParticle::copy_and_fill_solution: ElemList.size(): " << ElemList.size() << "\n"); + // use size of member 'CutElementHandler_FlatTop::m_vvvElemListCut' in order + // to indicate, whether a particle lies on a processor or not + std::vector ElemList = m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; + UG_LOG("1 MovingParticle::adjust_global_solution: ElemList.size(): " << ElemList.size() << "\n"); if (ElemList.size() == 0) { - UG_LOG( - "2 MovingParticle::copy_and_fill_solution: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + UG_LOG("2 MovingParticle::adjust_global_solution: ElemList.size(): " + << ElemList.size() << " => skip assembling! \n"); continue; } #endif - // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) - std::vector < DoFIndex > transInd = - m_spParticleHandlerGlobal->get_transInd(levIndex, p); - std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd( - levIndex, p); - - MathVector transSol = m_spParticleHandlerGlobal->get_transSol(p, - 0); - MathVector rotSol = m_spParticleHandlerGlobal->get_rotSol(p, 0); - - UG_LOG( - "in adjust_global_solution(): transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); - UG_LOG( - "in adjust_global_solution(): transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); - UG_LOG( - "in adjust_global_solution(): rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); - UG_LOG( - "in adjust_global_solution (): rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); - - ConstSmartPtr dd = - this->m_spApproxSpace->dof_distribution( - GridLevel(topLevel, GridLevel::LEVEL)); - typename TDomain::position_accessor_type aaPos = - m_spParticleHandlerGlobal->m_aaPos; - - const MathVector& center = m_spParticleHandlerGlobal->get_center( - p); - - typedef typename std::vector::iterator ListIter; - - // loop all elements relevant for prtIndex-th particle - std::vector ElemListLog = - m_spParticleHandlerGlobal->m_vvvElemListOutside[levIndex][p]; + MathVector transSol = m_spCutElementHandler->get_transSol(p,0); + MathVector rotSol = m_spCutElementHandler->get_rotSol(p, 0); - for (ListIter listIter = ElemListLog.begin(); - listIter != ElemListLog.end(); ++listIter) { - // get element + ConstSmartPtr dd = this->m_spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + typename TDomain::position_accessor_type aaPos = m_spCutElementHandler->m_aaPos; + typedef typename std::vector::iterator ListIter; + + const MathVector& center = m_spCutElementHandler->get_center(p); + + + // loop all elements relevant for p-th particle + std::vector ElemListLog = m_spCutElementHandler->m_vvvElemListOutside[levIndex][p]; + + for (ListIter listIter = ElemListLog.begin(); listIter != ElemListLog.end(); ++listIter) + { + // get element grid_base_object* elem = *listIter; - // collect all vertices of the element + // collect all vertices of the element std::vector vVertex; - CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + CollectVertices(vVertex, *m_spCutElementHandler->m_spMG, elem); - // loop vertices + // loop vertices for (size_t v = 0; v < vVertex.size(); ++v) { - // get vertex + // get vertex Vertex* vrt = vVertex[v]; for (size_t fct = 0; fct < dim; ++fct) { @@ -450,22 +470,20 @@ void MovingParticle::adjust_global_solution(vector_type& u, if (dd->inner_dof_indices(vrt, fct, vInd) != 1) UG_THROW("Only one index expected."); - // set solution: particle velocity + // set solution: particle velocity MathVector radialCo; VecSubtract(radialCo, aaPos[vrt], center); MathMatrix rotationMatCo = - m_spParticleHandlerGlobal->get_rotationMat( + m_spCutElementHandler->get_rotationMat( radialCo); - // set solution + // set solution: u = U + w x r DoFRef(u, vInd[0]) = transSol[fct]; for (int d = 0; d < dim; ++d) DoFRef(u, vInd[0]) += rotationMatCo[fct][d] * rotSol[d]; - DoFRef(u, vInd[0]) = 0.0; - + // DoFRef(u, vInd[0]) = 0.0; } - } // end vrt-loop } // end outsideElem-loop @@ -474,195 +492,90 @@ void MovingParticle::adjust_global_solution(vector_type& u, } template -void MovingParticle::fill_particle_solution(vector_type& u, - const int topLevel, const number time) { - - bool output = false; - - const char* filename = "freed_solution"; - std::string name(filename); - char ext[50]; - sprintf(ext, ".txt"); - name.append(ext); - FILE* outputFile = fopen(name.c_str(), "a"); - if (output) { - fprintf(outputFile, - "------------------------------------------------------------- \n"); - fprintf(outputFile, "-- 'fill_particle_solution()' for time = %e -- \n", - time); - fprintf(outputFile, - "------------------------------------------------------------- \n"); - } - +void MovingParticle:: +fill_freed_nodes(vector_type& u, const int topLevel, const number time) +{ +// get data const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { +// loop all particles + for (size_t p = 0; p < m_spCutElementHandler->num_particles(); ++p) + { #ifdef UG_PARALLEL + // use size of member 'CutElementHandler_FlatTop::m_vvvElemListCut' in order + // to indicate, whether a particle lies on a processor or not std::vector ElemList = - m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; - UG_LOG( - "1 MovingParticle::copy_and_fill_solution: ElemList.size(): " << ElemList.size() << "\n"); + m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; + UG_LOG("1 MovingParticle::fill_freed_nodes: ElemList.size(): " << ElemList.size() << "\n"); if (ElemList.size() == 0) { - UG_LOG( - "2 MovingParticle::copy_and_fill_solution: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + UG_LOG("2 MovingParticle::fill_freed_nodes: ElemList.size(): " + << ElemList.size() << " => skip assembling! \n"); continue; } #endif - // 'get_transInd()' returns NOT YET updated indices (updated during 'movingParticle:update()' vie lua) - std::vector < DoFIndex > transInd = - m_spParticleHandlerGlobal->get_transInd(levIndex, p); - std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd( - levIndex, p); - - MathVector transSol = m_spParticleHandlerGlobal->get_transSol(p,0); - MathVector rotSol = m_spParticleHandlerGlobal->get_rotSol(p, 0); - - UG_LOG( - "in fill_particle_solution(): transSol(0) = " << m_spParticleHandlerGlobal->get_transSol(p,0) << "\n"); - UG_LOG( - "in fill_particle_solution(): transSol(1) = " << m_spParticleHandlerGlobal->get_transSol(p, 1) << "\n"); - UG_LOG( - "in fill_particle_solution(): rotSol(0) = " << m_spParticleHandlerGlobal->get_rotSol(p,0) << "\n"); - UG_LOG( - "in fill_particle_solution(): rot1Sol(1) = " << m_spParticleHandlerGlobal->get_rotSol(p, 1) << "\n"); - - ConstSmartPtr dd = - this->m_spApproxSpace->dof_distribution( - GridLevel(topLevel, GridLevel::LEVEL)); - typename TDomain::position_accessor_type aaPos = - m_spParticleHandlerGlobal->m_aaPos; - - const MathVector& center = m_spParticleHandlerGlobal->get_center( - p); - - typedef typename std::vector::iterator ListIter; - - // loop all elements relevant for prtIndex-th particle - std::vector ElemListLog = - m_spParticleHandlerGlobal->m_vvvElemListOutside[levIndex][p]; - - /* for(ListIter listIter = ElemListLog.begin(); - listIter != ElemListLog.end(); ++listIter) - { - // get element - grid_base_object* elem = *listIter; - - // collect all vertices of the element - std::vector vVertex; - CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); - - // loop vertices - for(size_t v = 0; v < vVertex.size(); ++v) - { - // get vertex - Vertex* vrt = vVertex[v]; - - - for (size_t fct = 0; fct < dim; ++fct) - { - // create multi index - std::vector vInd; - // get multi indices - if(dd->inner_dof_indices(vrt, fct, vInd) != 1) - UG_THROW("Only one index expected."); - - // set solution: particle velocity - MathVector radialCo; - VecSubtract(radialCo, aaPos[vrt], center); - MathMatrix rotationMatCo = m_spParticleHandlerGlobal->get_rotationMat(radialCo); - - // set solution - DoFRef(u,vInd[0]) = transSol[fct]; - for ( int d = 0; d < dim; ++d ) - DoFRef(u,vInd[0]) += rotationMatCo[fct][d]*rotSol[d]; - - } - - - } // end vrt-loop - } // end outsideElem-loop - */ - // loop all elements relevant for prtIndex-th particle - ElemListLog = m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + ConstSmartPtr dd = this->m_spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + typename TDomain::position_accessor_type aaPos = m_spCutElementHandler->m_aaPos; + typedef typename std::vector::iterator ListIter; + + const MathVector& center = m_spCutElementHandler->get_center(p); + + MathVector transSol = m_spCutElementHandler->get_transSol(p,0); + MathVector rotSol = m_spCutElementHandler->get_rotSol(p, 0); + + + // loop all cut elements relevant for p-th particle + std::vector ElemListLog = m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; for (ListIter listIter = ElemListLog.begin(); - listIter != ElemListLog.end(); ++listIter) { - // get element + listIter != ElemListLog.end(); ++listIter) + { + // get element grid_base_object* elem = *listIter; - // collect all vertices of the element + // collect all vertices of the element std::vector vVertex; - CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + CollectVertices(vVertex, *m_spCutElementHandler->m_spMG, elem); - // loop vertices + // loop vertices for (size_t v = 0; v < vVertex.size(); ++v) { - // get vertex + // get vertex Vertex* vrt = vVertex[v]; - // ---> is_outsideFluid() is a geometrical check w.r.t new particle coords - // ---> m_spOutsideMarker was marked w.r.t old particle coords - // ===> !is_inside && is_outside = is_freed :-) - if (m_spParticleHandlerGlobal->is_outsideFluid_prtIndex(p, vrt) - && m_spParticleHandlerGlobal->m_spOutsideMarker->is_marked( - vrt)) { - if (1) { - fprintf(outputFile, " freed node: %e \t %e \t", - aaPos[vrt][0], aaPos[vrt][1]); - if (dim == 3) - fprintf(outputFile, " node: %e", aaPos[vrt][2]); - fprintf(outputFile, " time: %e \n\n", time); - } - + // ---> is_insideParticle_with_given_index() is a geometrical check w.r.t NEW particle coords + // (update_prtCoords() needs to be called BEFORE calling this method!) + // ---> m_spOutsideMarker was marked w.r.t OLD particle coords + // (update_interface_data() has to be called AFTER calling this method!) + // ===> !is_inside && is_outside = is_freed :-) + if ( m_spCutElementHandler->is_insideParticle_with_given_index(p, vrt) + && m_spCutElementHandler->m_spOutsideMarker->is_marked(vrt) ) + { for (size_t fct = 0; fct < dim; ++fct) { - // create multi index + // create multi index std::vector < DoFIndex > vInd; - // get multi indices + // get multi indices if (dd->inner_dof_indices(vrt, fct, vInd) != 1) UG_THROW("Only one index expected."); - // set solution: particle velocity + // set solution: particle velocity MathVector radialCo; VecSubtract(radialCo, aaPos[vrt], center); - MathMatrix rotationMatCo = - m_spParticleHandlerGlobal->get_rotationMat( - radialCo); - - if (output) - { - fprintf(outputFile, "fct = %lu:\n", fct); - fprintf(outputFile," transSol: %e, \t rotSol: %e\n", transSol[fct], rotSol[fct]); - fprintf(outputFile, " vorher: %e, \t", DoFRef(u, vInd[0])); - } - // set solution - DoFRef(u, vInd[0]) = transSol[fct]; + MathMatrix rotationMatCo = m_spCutElementHandler->get_rotationMat(radialCo); - if ( output) - { - UG_LOG(" fill_sol_: transInd(0) = " << transInd[0] << "\n"); - UG_LOG(" fill_sol_: rotInd(0) = " << rotInd[0] << "\n"); - UG_LOG(" fill_sol_: transSol[" << fct << "]: " << transSol[fct] << "\n"); - UG_LOG(" fill_sol_: rotSol[" << fct << "]: " << rotSol[fct] << "\n"); - } - + // set solution + DoFRef(u, vInd[0]) = transSol[fct]; for (int d = 0; d < dim; ++d) - DoFRef(u, vInd[0]) += rotationMatCo[fct][d] - * rotSol[d]; + DoFRef(u, vInd[0]) += rotationMatCo[fct][d] * rotSol[d]; - if (output) - fprintf(outputFile, " nachher: %e \n\n", - DoFRef(u, vInd[0])); } - // wenn node ganz im Inneren vom Partikel liegt (!FlatTopVrtMarker), dann hat sich das Partikel zu schnell - // weiterbewegt -> CFL-Schranke verletzt! - if (!m_spParticleHandlerGlobal->m_spFlatTopVrtMarker->is_marked( - vrt) - && m_spParticleHandlerGlobal->m_spOutsideMarker->is_marked( - vrt)) - UG_THROW( - "in 'fill_particle_solution()': CFL-Schranke verletzt!\n"); + // if vertex lies outside particle and NOT near interface, i.e. !FlatTopVrtMarker = true, + // then the particle moved to fast in the last timestep + // ==> CFL criterion not satisfied + if (!m_spCutElementHandler->m_spInterfaceVrtMarker->is_marked(vrt) + && m_spCutElementHandler->m_spOutsideMarker->is_marked(vrt)) + UG_THROW("in 'fill_freed_nodes()': CFL criterion not satisfied!\n"); } } // end vrt-loop @@ -670,63 +583,48 @@ void MovingParticle::fill_particle_solution(vector_type& u, } // end prt-loop - fclose(outputFile); - } -template -void MovingParticle::clear_solution(vector_type& u, - const int topLevel) { -// const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - -} // call via lua BEFORE applying 'movingParticle:update()', which changes the global indices of trandSol/rotSol // necessary for re-writing solution to NEW indices of vector 'u' during 'update_solution' -// => handling instance/buffering data := m_spParticleHandlerGlobal->(m_vSolTrans/m_vSolRot) +// => handling instance/buffering data := m_spCutElementHandler->(m_vSolTrans/m_vSolRot) // transfer direction: m_vSolTrans ---> DoFRef(u, transInd) template -void MovingParticle::update_particle_solution(vector_type& u, const int topLevel) +void MovingParticle:: +write_particle_velocity(vector_type& u, const int topLevel) { const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { - + for (size_t p = 0; p < m_spCutElementHandler->num_particles(); ++p) + { #ifdef UG_PARALLEL + // use size of member 'CutElementHandler_FlatTop::m_vvvElemListCut' in order to indicate, + // whether a particle lies on a processor or not std::vector ElemList = - m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; - UG_LOG( - "1 MovingParticle::update_solution: ElemList.size(): " << ElemList.size() << "\n"); + m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; + UG_LOG("1 MovingParticle::write_particle_velocity: ElemList.size(): " << ElemList.size() << "\n"); if (ElemList.size() == 0) { - UG_LOG( - "2 MovingParticle::update_solution: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); + UG_LOG("2 MovingParticle::write_particle_velocity: ElemList.size(): " + << ElemList.size() << " => skip assembling! \n"); continue; } #endif - // 'get_transInd()' returns allready updated indices (updated during 'movingParticle:update()' vie lua) - std::vector < DoFIndex > transInd = m_spParticleHandlerGlobal->get_transInd(levIndex, p); - std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd(levIndex, p); + // 'get_transInd()' returns allready updated indices (updated during 'movingParticle:update()' via lua) + std::vector < DoFIndex > transInd = m_spCutElementHandler->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spCutElementHandler->get_rotInd(levIndex, p); - UG_LOG("in 'update_particle_solution()': transInd = " << transInd[0] << "\n"); - UG_LOG("in 'update_particle_solution()': rotInd = " << rotInd[0] << "\n"); +// UG_LOG("in 'write_particle_velocity()': transInd = " << transInd[0] << "\n"); +// UG_LOG("in 'write_particle_velocity()': rotInd = " << rotInd[0] << "\n"); - for (int d = 0; d < dim; ++d) { -#ifdef UG_DEBUG - UG_LOG( - "VORHER: in 'update_solution()': DoFRef(u, transInd[d]) = " << DoFRef(u, transInd[d]) << "\n"); - UG_LOG( - "VORHER: in 'update_solution()': DoFRef(u, rotInd[d]) = " << DoFRef(u, rotInd[d]) << "\n"); -#endif - DoFRef(u, transInd[d]) = m_spParticleHandlerGlobal->get_transSol(p,0)[d]; - DoFRef(u, rotInd[d]) = m_spParticleHandlerGlobal->get_rotSol(p, 0)[d]; -#ifdef UG_DEBUG - UG_LOG( - "NACHHER: in 'update_solution()': DoFRef(u, transInd[d]) = " << DoFRef(u, transInd[d]) << "\n"); - UG_LOG( - "NACHHER: in 'update_solution()': DoFRef(u, rotInd[d]) = " << DoFRef(u, rotInd[d]) << "\n"); -#endif + for (int d = 0; d < dim; ++d) + { + // write solution to the GridFunction 'u' into the vertices, where their DoFs were allocated + DoFRef(u, transInd[d]) = m_spCutElementHandler->get_transSol(p,0)[d]; + DoFRef(u, rotInd[d]) = m_spCutElementHandler->get_rotSol(p, 0)[d]; + } } // end particle loop @@ -734,38 +632,33 @@ void MovingParticle::update_particle_solution(vector_type& u, } - template - bool MovingParticle::mark_collision_area(SmartPtr refiner, int level) - { - - //typedef typename TDomain::position_accessor_type position_accessor_type; - typedef typename GeomObjBaseTypeByDim::base_obj_type elem_t; - //typedef typename ElementStorage::SectionContainer::iterator BaseElemIterator; - //typedef typename elem_t::side side_t; - //typedef typename std::vector::iterator ElemIterator; - typedef typename std::map::iterator ElemMapIterator; - - typedef typename geometry_traits::iterator ElemIterator; +template +bool MovingParticle:: +mark_collision_area(SmartPtr refiner, int level) +{ - bool elem_is_cut_by_2 = false; + typedef typename GeomObjBaseTypeByDim::base_obj_type elem_t; + typedef typename std::map::iterator ElemMapIterator; + typedef typename geometry_traits::iterator ElemIterator; - std::map num_cuts; + bool elem_is_cut_by_2 = false; - // access the grid and the position attachment - MultiGrid* mg = (refiner->multi_grid()); - //position_accessor_type& aaPos = dom.position_accessor(); + std::map num_cuts; - for (ElemIterator elemIter = mg->begin(); elemIter != mg->end(); ++elemIter) { +// access the grid and the position attachment + MultiGrid* mg = (refiner->multi_grid()); + + for (ElemIterator elemIter = mg->begin(); elemIter != mg->end(); ++elemIter) { elem_t* elem = *elemIter; - for (size_t p = 0; p < m_spParticleHandlerGlobal->num_particles(); ++p) { + for (size_t p = 0; p < m_spCutElementHandler->num_particles(); ++p) { //std::vector ElemListLog = m_vvvElemListCut[level][p]; //for (ElemIterator elem = ElemListLog.begin(); //elem != ElemListLog.end(); ++elem) { bool cut = false; for (size_t v = 0; v < elem->num_vertices(); ++v) { - const MathVector& vrtPos = m_spParticleHandlerGlobal->m_aaPos[elem->vertex(v)]; - const MathVector& center = m_spParticleHandlerGlobal->get_center(p); - const number radius = m_spParticleHandlerGlobal->get_radius(p); + const MathVector& vrtPos = m_spCutElementHandler->m_aaPos[elem->vertex(v)]; + const MathVector& center = m_spCutElementHandler->get_center(p); + const number radius = m_spCutElementHandler->get_radius(p); if (VecDistance(vrtPos, center) <= radius) { cut = true; @@ -785,13 +678,16 @@ void MovingParticle::update_particle_solution(vector_type& u, return elem_is_cut_by_2; } - template - double MovingParticle::estimate_repulsive_force_parameters(vector_type& u, int topLevel, double maxElemDiameter, double deltaT){ - // Get and synchronize velocities +template +double MovingParticle:: +estimate_repulsive_force_parameters(vector_type& u, int topLevel, double maxElemDiameter, double deltaT) +{ + + // Get and synchronize velocities const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); std::vector > transVel; - int num_particles = m_spParticleHandlerGlobal->num_particles(); + size_t num_particles = m_spCutElementHandler->num_particles(); transVel.resize(num_particles); bool verbose = false; @@ -803,14 +699,14 @@ void MovingParticle::update_particle_solution(vector_type& u, for (size_t p = 0; p < num_particles; ++p) { std::vector ElemList = - m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; if (ElemList.size() == 0) { for (int d = 0; d < dim; ++d) { transVelP[d] = 0.0; } } else { std::vector < DoFIndex > transInd = - m_spParticleHandlerGlobal->get_transInd(levIndex, p); + m_spCutElementHandler->get_transInd(levIndex, p); for (int d = 0; d < dim; ++d) { transVelP[d] = DoFRef(u, transInd[d]); @@ -838,7 +734,7 @@ void MovingParticle::update_particle_solution(vector_type& u, #else for (size_t p = 0; p < num_particles; ++p) { std::vector < DoFIndex > transInd = - m_spParticleHandlerGlobal->get_transInd(levIndex, p); + m_spCutElementHandler->get_transInd(levIndex, p); for (int d = 0; d < dim; ++d) { transVelP[d] = DoFRef(u, transInd[d]); @@ -851,9 +747,9 @@ void MovingParticle::update_particle_solution(vector_type& u, for (size_t p = 0; p < num_particles; ++p){ // Get values for particle p - MathVector center_p = m_spParticleHandlerGlobal->get_center(p); + MathVector center_p = m_spCutElementHandler->get_center(p); VecScaleAdd(center_p, 1.0, center_p, deltaT, transVel[p]); - number radius_p = m_spParticleHandlerGlobal->get_radius(p); + number radius_p = m_spCutElementHandler->get_radius(p); //double Mass_p = m_spInterfaceMapper->Mass(13957,p); for (size_t q = 0; q < num_particles; ++q){ if (p == q) { @@ -862,9 +758,9 @@ void MovingParticle::update_particle_solution(vector_type& u, if (verbose) UG_LOG("p = "< center_q = m_spParticleHandlerGlobal->get_center(q); + MathVector center_q = m_spCutElementHandler->get_center(q); VecScaleAdd(center_q, 1.0, center_q, deltaT, transVel[q]); - number radius_q = m_spParticleHandlerGlobal->get_radius(q); + number radius_q = m_spCutElementHandler->get_radius(q); //double Mass_q = m_spInterfaceMapper->Mass(13957,q); // Calculate force if (verbose) { @@ -903,10 +799,85 @@ void MovingParticle::update_particle_solution(vector_type& u, eps = std::max(eps,dist); } } - return eps; - } + + return eps; +} +#ifdef UG_PARALLEL +template +void MovingParticle:: +pre_balancing_update(vector_type& u, SmartPtr > spApproxSpace, + const int baseLevel, const int topLevel, const number time, number deltaT) +{ + int topLev = spApproxSpace->num_levels()-1; + if ( topLev != topLevel ) + UG_THROW("NavierStokes::update: parameter 'topLevel' = " << topLevel << " != " + << topLev << "current top leven! \n"); + + const char* filename = "update_times"; + std::string name(filename); + char ext[50]; + sprintf(ext, "_%d.txt", pcl::ProcRank()); + //sprintf(ext, ".txt"); + name.append(ext); + FILE* outputFile = fopen(name.c_str(), "a"); + + std::clock_t begin = std::clock(); + // A. copy solution to data: DoFRef(u, transInd) ---> m_vSolTrans + // reverse direction done during 'NavierStokes::write_particle_velocity()' + store_particle_velocity(u, topLevel); + std::clock_t end = std::clock(); + fprintf(outputFile,"store_particle_velocity %f", double(end - begin) / CLOCKS_PER_SEC); + + begin = std::clock(); + + // C. calculate new particle coordinates + m_spCutElementHandler->update_prtCoords(topLevel, deltaT); + end = std::clock(); + fprintf(outputFile,"update_prtCoords %f", double(end - begin) / CLOCKS_PER_SEC); + + begin = std::clock(); + + // B. synchronize particle data when everything in ParticleProvider is up to date. + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + m_spCutElementHandler->synchronize_particles(levIndex); + + end = std::clock(); + fprintf(outputFile,"synchronize_particles %f", double(end - begin) / CLOCKS_PER_SEC); + + begin = std::clock(); + + // D. fill particle nodes with their real solution + // --> FIRST store_particle_velocity() necessary, since eventually during + // fill extraDoF-nodes will be overwriten + fill_freed_nodes(u, topLevel, time); + end = std::clock(); + fprintf(outputFile,"fill_freed_nodes %f", double(end - begin) / CLOCKS_PER_SEC); + + fclose(outputFile); + +} + + +template +void MovingParticle:: +post_balancing_update(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel, const number time, number deltaT) +{ + // E. update data => new node for (u, transInd) ! + ConstSmartPtr dd = spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); + m_spCutElementHandler->template init(dd, baseLevel, topLevel); + + // F. update solution from data: m_vSolTransDoFRef(u, transInd) + // transfer direction: m_vSolTrans ---> DoFRef(u, transInd) + write_particle_velocity(u, topLevel); + + // reset volume: + m_spInterfaceMapper->reset_volume(); +} +#endif /* UG_PARALLEL */ + + } // end namespace NavierStokes } // end namespace ug diff --git a/incompressible/fv1/moving_particle/moving_particle_tools.h b/incompressible/fv1/moving_particle/moving_particle_tools.h index 5f81590..6f84d12 100644 --- a/incompressible/fv1/moving_particle/moving_particle_tools.h +++ b/incompressible/fv1/moving_particle/moving_particle_tools.h @@ -16,7 +16,7 @@ template void MovingParticle:: interpolate_point(ConstSmartPtr dd, const vector_type& u, - const MathVector& evalPos, // input data + const MathVector& evalPos, // input data MathVector& interpolation) // output data { MathVector localPos(0.0); @@ -25,7 +25,7 @@ interpolate_point(ConstSmartPtr dd, typename TDomain::position_accessor_type aaPos = this->m_spApproxSpace->domain()->position_accessor(); // create Function Group - FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spParticleHandlerGlobal->m_fctNames)); + FunctionGroup fctGrp(dd->function_pattern(), TokenizeString(m_spCutElementHandler->m_fctNames)); // get iterators for all elems on subset typedef typename DoFDistribution::dim_traits::grid_base_object grid_base_object; @@ -35,55 +35,55 @@ interpolate_point(ConstSmartPtr dd, iterEnd = dd->end(); - // loop elements in order to compute 'U_global' and 'omega_global': - for( ; iter != iterEnd; ++iter) +// loop elements in order to compute 'U_global' and 'omega_global': + for( ; iter != iterEnd; ++iter) { - // get element + // get element grid_base_object* elem = *iter; if ( ContainsPoint(elem, evalPos, aaPos) ) { - // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...) + // get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...) ReferenceObjectID roid = (ReferenceObjectID) elem->reference_object_id(); - // get all corner coordinates + // get all corner coordinates std::vector > vCorner; CollectCornerCoordinates(vCorner, *elem, aaPos, true); - // get the reference mapping for the element using global corners + // get the reference mapping for the element using global corners DimReferenceMapping& mapping = ReferenceMappingProvider::get(roid, vCorner); - // compute global integration points + // compute global integration points mapping.global_to_local(localPos, evalPos); - // loop all velocity components + // loop all velocity components for(int cmp = 0; cmp < dim+1; ++cmp) { - // get fct id for compent + // get fct id for compent const size_t fct = fctGrp[cmp]; - // local finite element id + // local finite element id const LFEID m_id = dd->local_finite_element_id(fct); - // get trial space + // get trial space const LocalShapeFunctionSet& rTrialSpace = LocalFiniteElementProvider::get(roid, m_id); - // number of dofs on element + // number of dofs on element const size_t num_sh = rTrialSpace.num_sh(); - // get multiindices of element + // get multiindices of element std::vector ind; // aux. index array dd->dof_indices(elem, fct, ind); - // check multi indices + // check multi indices if(ind.size() != num_sh) UG_THROW("L2ErrorIntegrand::evaluate: Wrong number of" " multi indices."); - // compute approximated solution at integration point + // compute approximated solution at integration point interpolation[cmp] = 0.0; for(size_t sh = 0; sh < num_sh; ++sh) { @@ -97,45 +97,33 @@ interpolate_point(ConstSmartPtr dd, } } // end cmp-loop - } // end if-ContainsPoint - - } // end element-loop - //UG_LOG("end: interpolation = " << interpolation[dim] << "\n"); - } +} template void MovingParticle:: print_pressure_nodal(const vector_type& u, const int topLevel) { - UG_LOG("START print_pressure_nodal()\n"); - FILE *pressure; - char filename1[40]; - sprintf(filename1, "pressure_nodal_teta_level%d.txt", topLevel); - pressure = fopen(filename1, "w"); - FILE *pressure_on_interface; - char filename2[40]; - sprintf(filename2, "pressure_nodal_teta_level_ON_interface%d.txt", topLevel); - pressure_on_interface = fopen(filename2, "w"); + char filename[40]; + sprintf(filename, "pressure_profile_level%d.txt", topLevel); + pressure = fopen(filename, "w"); int numIter = 0; number dist = 0.0; const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - std::vector ElemListLog = m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][0]; + std::vector ElemListLog = m_spCutElementHandler->m_vvvElemListCut[levIndex][0]; ConstSmartPtr dd = this->m_spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - typename TDomain::position_accessor_type aaPos = m_spParticleHandlerGlobal->m_aaPos; - - const MathVector& center = m_spParticleHandlerGlobal->get_center(0); + typename TDomain::position_accessor_type aaPos = m_spCutElementHandler->m_aaPos; - UG_LOG("center " << center << "\n"); + const MathVector& center = m_spCutElementHandler->get_center(0); typedef typename std::vector::iterator ListIter; - // loop all elements relevant for prtIndex-th particle +// loop all cut elements in order to print pressure for fluid nodes, which lie near the interface for(ListIter listIter = ElemListLog.begin(); listIter != ElemListLog.end(); ++listIter) { @@ -145,7 +133,7 @@ print_pressure_nodal(const vector_type& u, const int topLevel) // collect all vertices of the element std::vector vVertex; - CollectVertices(vVertex, *m_spParticleHandlerGlobal->m_spMG, elem); + CollectVertices(vVertex, *m_spCutElementHandler->m_spMG, elem); MathVector bufferVector; VecSubtract(bufferVector, aaPos[vVertex[0]], aaPos[vVertex[2]]); @@ -157,7 +145,8 @@ print_pressure_nodal(const vector_type& u, const int topLevel) // get vertex Vertex* vrt = vVertex[v]; - if ( !m_spParticleHandlerGlobal->is_outsideFluid(vrt) ) + // print value for vertices in the fluid and near the interface: + if ( !m_spCutElementHandler->is_outsideFluid(vrt) ) { std::vector vInd; if(dd->inner_dof_indices(vrt, dim, vInd) != 1) @@ -174,44 +163,23 @@ print_pressure_nodal(const vector_type& u, const int topLevel) fprintf(pressure, "%e \t %e \t %lu # teta, value pressure, KnotenIndex vInd[0] \n", teta, DoFRef(u, vInd[0]), vInd[0][0]); } - if ( m_spParticleHandlerGlobal->is_outsideFluid(vrt) ) - { - std::vector vInd; - if(dd->inner_dof_indices(vrt, dim, vInd) != 1) - UG_THROW("Only one index expected."); - - MathVector radialVector; - radialVector[0] = aaPos[vrt][0]-center[0]; - radialVector[1] = aaPos[vrt][1]-center[1]; - - number teta = atan2(aaPos[vrt][1]-center[1], aaPos[vrt][0]-center[0]); - if ( teta < 0.0 ) - teta += 2*3.1415926; - - fprintf(pressure_on_interface, "%e \t %e \t %lu # teta, value pressure, KnotenIndex vInd[0] \n", teta, DoFRef(u, vInd[0]), vInd[0][0]); - - } } } fclose(pressure); - fclose(pressure_on_interface); - UG_LOG("print_pressure_nodal() done...\n"); } template void MovingParticle:: print_deltaP(const vector_type& u, const int topLevel) { - UG_LOG("START print_pressure()\n"); - FILE *pressure; - char filename1[40]; - sprintf(filename1, "delta_pressure_level%d.txt", topLevel); - pressure = fopen(filename1, "w"); + char filename[40]; + sprintf(filename, "delta_p_level%d.txt", topLevel); + pressure = fopen(filename, "w"); ConstSmartPtr dd = this->m_spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); @@ -230,28 +198,22 @@ print_deltaP(const vector_type& u, const int topLevel) number deltaP = interpolVal1[dim] - interpolVal2[dim]; - UG_LOG("interpolVal1[" << dim<< "] = " << interpolVal1[dim] << "\n"); - UG_LOG("interpolVal2[" << dim<< "] = " << interpolVal2[dim] << "\n"); - UG_LOG("deltaP = " << deltaP << "\n"); - - fprintf(pressure, "%e \t %e \t %e \n# interpolVal1[dim], interpolVal1[dim], deltaP\n", interpolVal1[dim], interpolVal2[dim], deltaP); + fprintf(pressure, "%e \t %e \t %e \n# interpolVal1[dim], interpolVal2[dim], deltaP\n", interpolVal1[dim], interpolVal2[dim], deltaP); fclose(pressure); } template void MovingParticle:: -print_pressure(const vector_type& u, const int topLevel) +print_pressure_teta(const vector_type& u, const int topLevel) { - UG_LOG("START print_pressure()\n"); - FILE *pressure; - char filename1[40]; - sprintf(filename1, "pressure_MovPrtSTdFV_teta_level%d.txt", topLevel); - pressure = fopen(filename1, "w"); + char filename[40]; + sprintf(filename, "pressure_teta_level%d.txt", topLevel); + pressure = fopen(filename, "w"); ConstSmartPtr dd = this->m_spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - const MathVector& center = m_spParticleHandlerGlobal->get_center(0); + const MathVector& center = m_spCutElementHandler->get_center(0); size_t t_max = 500; MathVector printPos; @@ -273,83 +235,25 @@ print_pressure(const vector_type& u, const int topLevel) fclose(pressure); - //UG_THROW("Vorsicht bei Enwednugn von 'print_pressure()': früher wurde der Vektor 'interpolVal' an der Stelle dim+1 statt dim ausgelesen!!\n"); } - /* -template -void MovingParticle:: -compute_error_on_circle(const vector_type& u, const int topLevel, number r) -{ - FILE *solution; - char filename1[40]; - sprintf(filename1, "error_MovPrt_radius%e_level%d.txt", r, topLevel); - solution = fopen(filename1, "w"); - - const MathVector& center = m_spParticleHandlerGlobal->get_center(0); - const number R = m_spParticleHandlerGlobal->get_radius(0); - ConstSmartPtr dd = this->m_spApproxSpace->dof_distribution(GridLevel(topLevel, GridLevel::LEVEL)); - - number error_u = 0.0; - number error_v = 0.0; - number error_p = 0.0; - - size_t t_max = 500; - MathVector printPos; - MathVector interpolVal; - for(size_t t = 0; t < t_max; ++t) - { - number teta = t*(2*PI/t_max); - number co = cos(teta); - number si = sin(teta); - printPos[0] = r*co + center[0]; - printPos[1] = r*si + center[1]; - interpolate_point(dd, u, printPos, interpolVal); - - number sol_u = ((R*R-r*r)*co*co + r*r*log(r/R) + 0.5*(r*r-R*R))/(r*r); - number sol_v = ((R*R-r*r)*si*co)/(r*r); - number sol_p = -2*co*r; - - error_u += fabs(interpolVal[0]-sol_u); - error_v += fabs(interpolVal[1]-sol_v); - error_p += fabs(interpolVal[2]-sol_p); - - fprintf(solution, "%e \t", teta); - for ( size_t i = 0; i <= dim; ++i) - fprintf(solution, "%e \t", interpolVal[i]); - - fprintf(solution, "%e \t %e # teta, interpolVal[0], interpolVal[1], interpolVal[2], printPos[0], printPot[1]\n", printPos[0], printPos[1]); - - } - - fclose(solution); - - UG_LOG("error_u: " << error_u/500 << "\n"); - UG_LOG("error_v: " << error_v/500 << "\n"); - UG_LOG("error_p: " << error_p/500 << "\n\n"); - -} -*/ template void MovingParticle:: print_velocity(const vector_type& u, const int topLevel, number time, const char* filename) { - UG_LOG("MovingParticle::print_velocity(): Start: \n"); - - // Parameter von class 'MovingParticle' extrahieren: +// Parameter von class 'MovingParticle' extrahieren: const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); const bool isTimedep = is_time_dependent(); - size_t numPrt = m_spParticleHandlerGlobal->num_particles(); - -// if ( numPrt > 2 ) -// UG_THROW("Particle:output_velocity: VORSICHT, output nicht implementiert fuer mehr als 2 particle! -> m_bShared[][] ist Problem! ... Exit! \n"); + size_t numPrt = m_spCutElementHandler->num_particles(); for(size_t p = 0; p < numPrt; ++p) { #ifdef UG_PARALLEL - std::vector ElemList = m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; + // use size of member 'CutElementHandler_FlatTop::m_vvvElemListCut' in order to indicate, + // whether a particle lies on a processor or not + std::vector ElemList = m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; UG_LOG("1 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << "\n"); if (ElemList.size() == 0) { UG_LOG("2 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); @@ -357,11 +261,11 @@ print_velocity(const vector_type& u, const int topLevel, number time, const char } #endif - // Parameter von class 'CutElementHandler' extrahieren: - - // get multiindices for translation and rotation of particle - std::vector < DoFIndex > transInd = m_spParticleHandlerGlobal->get_transInd(levIndex, p); - std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd(levIndex, p); + // Parameter von class 'CutElementHandler' extrahieren: + + // get multiindices for translation and rotation of particle + std::vector < DoFIndex > transInd = m_spCutElementHandler->get_transInd(levIndex, p); + std::vector < DoFIndex > rotInd = m_spCutElementHandler->get_rotInd(levIndex, p); MathVector transSol; MathVector rotSol; @@ -373,127 +277,11 @@ print_velocity(const vector_type& u, const int topLevel, number time, const char } // auf untergeordnete class 'ParticleProvider' weiterleiten: - m_spParticleHandlerGlobal->print_velocity(transSol, rotSol, p, isTimedep, time, filename); + m_spCutElementHandler->print_velocity(transSol, rotSol, p, isTimedep, time, filename); } - UG_LOG("output_velocity....DONE\n"); - } - /* - -template -void MovingParticle:: -print_velocity_many_particles(const vector_type& u, const int topLevel, number time, const char* filename) -{ - UG_LOG("MovingParticle::print_velocity(): Start: \n"); - - size_t numPrt = m_spParticleHandlerGlobal->num_particles(); - - const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - number distance = -10.0; - - // compute distance between 2 particles - if ( numPrt == 2 ) - { - const number radius1 = m_spParticleHandlerGlobal->get_radius(0); - const number radius2 = m_spParticleHandlerGlobal->get_radius(1); - - const number radius = radius1+radius2; - - MathVector distVec; - VecSubtract(distVec, m_spParticleHandlerGlobal->get_center(1), m_spParticleHandlerGlobal->get_center(0)); - - distance = VecDot(distVec, distVec); - distance = sqrt(distance); - distance = distance - radius; - } - for(size_t p = 0; p < numPrt; ++p) - { - -#ifdef UG_PARALLEL - std::vector ElemList = m_spParticleHandlerGlobal->m_vvvElemListCut[levIndex][p]; - UG_LOG("1 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << "\n"); - if (ElemList.size() == 0) { - UG_LOG("2 MovingParticle::output_velocity: ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); - continue; - } -#endif - // get multiindices for translation and rotation of particle - std::vector < DoFIndex > transInd = m_spParticleHandlerGlobal->get_transInd(levIndex, p); - std::vector < DoFIndex > rotInd = m_spParticleHandlerGlobal->get_rotInd(levIndex, p); - - MathVector transSol; - MathVector rotSol; - - MathVector center = m_spParticleHandlerGlobal->get_center(p); - const number radius = m_spParticleHandlerGlobal->get_radius(p); - - for ( int d = 0; d < dim; ++d ) - { - transSol[d] = DoFRef(u, transInd[d]); - rotSol[d] = DoFRef(u, rotInd[d]); - } - number f1 = 0.0; - number gravity = -9.81; - if ( !is_time_dependent() ) - f1 = transSol[0]*4.0/(radius*radius*gravity); - - std::string name(filename); - - char * cstr = new char [name.size()+1]; - strcpy (cstr, name.c_str()); - - - if ( !is_time_dependent() ) - { - FILE* print_velocity = fopen(name.c_str(), "a"); - - - fprintf(print_velocity,"%e \t %e \t ",radius, f1); - for ( int d = 0; d < dim; ++d ) - fprintf(print_velocity,"%e \t %e \t ", transSol[d], rotSol[d]); - for ( int d = 0; d < dim; ++d ) - fprintf(print_velocity,"%e \t ", center[d]); - - fprintf(print_velocity," # radius, f1, transVel[0], rotVel[0], transVel[1], rotVel[1], center_coords, (m_bSharedIP = "); - fprintf(print_velocity, "0 ), "); - - fprintf(print_velocity," (m_bSharedElem = "); - fprintf(print_velocity, "0 ) \n "); - fclose(print_velocity); - - } - else - { - FILE* print_velocity = fopen(name.c_str(), "a"); - - fprintf(print_velocity,"%e \t ",time); - - for ( int d = 0; d < dim; ++d ) - fprintf(print_velocity,"%e \t %e \t ", transSol[d], rotSol[d]); - - for ( int d = 0; d < dim; ++d ) - fprintf(print_velocity,"%e \t ", center[d]); - - - fprintf(print_velocity,"%e \t ", distance); - - fprintf(print_velocity," # time, transVel[0], rotVel[0], transVel[1], rotVel[1], center_coords, (m_bSharedIP = "); - fprintf(print_velocity, "0 ), "); - - fprintf(print_velocity," (m_bSharedElem = "); - fprintf(print_velocity, "0 ) \n "); - fclose(print_velocity); - - } - - } - - UG_LOG("output_velocity....DONE\n"); - -} -*/ } // end namespace NavierStokes } // end namespace ug diff --git a/incompressible/fv1/navier_stokes_fv1.cpp b/incompressible/fv1/navier_stokes_fv1.cpp index b770221..0a31f73 100644 --- a/incompressible/fv1/navier_stokes_fv1.cpp +++ b/incompressible/fv1/navier_stokes_fv1.cpp @@ -32,11 +32,15 @@ #include "navier_stokes_fv1.h" -#include "lib_disc/spatial_disc/disc_util/fv1FT_geom.h" +#include "lib_disc/spatial_disc/disc_util/fv1_geom.h" +//#include "lib_disc/spatial_disc/disc_util/fv1FT_geom.h" #include "lib_disc/spatial_disc/disc_util/geom_provider.h" +//#include "moving_particle/interface_handler_particle.h" namespace ug{ +//template +//class InterfaceHandlerLocalParticle; namespace NavierStokes{ @@ -104,8 +108,6 @@ prepare_setting(const std::vector& vLfeID, bool bNonRegularGrid) UG_THROW("NavierStokes: 'fv1' expects Lagrange P1 trial space " "for velocity and pressure."); - m_LFEID = vLfeID[0]; - // update assemble functions register_all_funcs(false); } @@ -133,6 +135,7 @@ set_source(SmartPtr, dim> > data) m_imSourceSCVF.set_data(data); } + //////////////////////////////////////////////////////////////////////////////// // assembling functions //////////////////////////////////////////////////////////////////////////////// @@ -150,16 +153,16 @@ prep_elem_loop(const ReferenceObjectID roid, const int si) // check, that stabilization has been set if(m_spStab.invalid()) UG_THROW("Stabilization has not been set."); - + // init stabilization for element type m_spStab->template set_geometry_type(); - + if (! m_bStokes) // no convective terms in the Stokes eq. => no upwinding { // check, that convective upwinding has been set if(m_spConvStab.invalid() && m_spConvUpwind.invalid()) UG_THROW("Upwinding for convective Term in Momentum eq. not set."); - + // init convection stabilization for element type if(m_spConvStab.valid()) m_spConvStab->template set_geometry_type(); @@ -183,13 +186,12 @@ prep_elem_loop(const ReferenceObjectID roid, const int si) if(!m_imDensitySCV.data_given()) UG_THROW("NavierStokes::prep_elem_loop:" " Density has not been set, but is required."); - + // set local positions for imports - //if(!TFVGeom::usesHangingNodes) - if(!TFVGeom::usesHangingNodes && TFVGeom::staticLocalData) + if(!TFVGeom::usesHangingNodes) { static const int refDim = TElem::dim; - TFVGeom& geo = GeomProvider::get(m_LFEID, 1); + TFVGeom& geo = GeomProvider::get(); const MathVector* vSCVFip = geo.scvf_local_ips(); const size_t numSCVFip = geo.num_scvf_ips(); const MathVector* vSCVip = geo.scv_local_ips(); @@ -200,9 +202,10 @@ prep_elem_loop(const ReferenceObjectID roid, const int si) m_imSourceSCV.template set_local_ips(vSCVip,numSCVip); m_imSourceSCVF.template set_local_ips(vSCVFip,numSCVFip); } - + } + template template void NavierStokesFV1:: @@ -216,16 +219,15 @@ void NavierStokesFV1:: prep_elem(const LocalVector& u, GridObject* elem, ReferenceObjectID roid, const MathVector vCornerCoords[]) { // Update Geometry for this element - TFVGeom& geo = GeomProvider::get(m_LFEID, 1); - try{ + TFVGeom& geo = GeomProvider::get(); + try{ geo.update(elem, vCornerCoords, &(this->subset_handler())); } UG_CATCH_THROW("NavierStokes::prep_elem:" " Cannot update Finite Volume Geometry."); // set local positions for imports - //if(TFVGeom::usesHangingNodes) - if(TFVGeom::usesHangingNodes || !TFVGeom::staticLocalData) + if(TFVGeom::usesHangingNodes) { // request ip series static const int refDim = TElem::dim; @@ -256,14 +258,13 @@ prep_elem(const LocalVector& u, GridObject* elem, ReferenceObjectID roid, const template template void NavierStokesFV1:: -add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, - const MathVector vCornerCoords[]) +add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) { // Only first order implementation UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); + static const TFVGeom& geo = GeomProvider::get(); // check for source term to pass to the stabilization const DataImport, dim>* pSource = NULL; @@ -287,8 +288,8 @@ add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, } // interpolate velocity at ip with standard lagrange interpolation - //static const size_t numSCVF = TFVGeom::numSCVF; - static const size_t numSCVF = TFVGeom::maxNumSCVF; + static const size_t numSCVF = TFVGeom::numSCVF; +// static const size_t numSCVF = TFVGeom::maxNumSCVF; MathVector StdVel[numSCVF]; for(size_t ip = 0; ip < geo.num_scvf(); ++ip) @@ -608,13 +609,11 @@ template void NavierStokesFV1:: add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) { - //UG_LOG("Anfang add_def_A_elem"); - // Only first order implemented UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); + static const TFVGeom& geo = GeomProvider::get(); // check for source term to pass to the stabilization const DataImport, dim>* pSource = NULL; @@ -638,8 +637,9 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat } // interpolate velocity at ip with standard lagrange interpolation - //static const size_t numSCVF = TFVGeom::numSCVF; - static const size_t numSCVF = TFVGeom::maxNumSCVF; + + static const size_t numSCVF = TFVGeom::numSCVF; + // static const size_t numSCVF = TFVGeom::maxNumSCVF; MathVector StdVel[numSCVF]; for(size_t ip = 0; ip < geo.num_scvf(); ++ip) @@ -702,9 +702,10 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat gradVel(d1, d2) = 0.0; for(size_t sh = 0; sh < scvf.num_sh(); ++sh) gradVel(d1, d2) += scvf.global_grad(sh)[d2] - * u(d1, sh); + * u(d1, sh); } + // 2. Compute flux MathVector diffFlux; @@ -786,7 +787,6 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat d(_P_, scvf.from()) += contFlux; d(_P_, scvf.to() ) -= contFlux; } - } @@ -799,7 +799,7 @@ add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); + static const TFVGeom& geo = GeomProvider::get(); // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) @@ -829,7 +829,7 @@ add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); + static const TFVGeom& geo = GeomProvider::get(); // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) @@ -862,7 +862,7 @@ add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoor if(!m_imSourceSCV.data_given()) return; // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); + static const TFVGeom& geo = GeomProvider::get(); // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) @@ -919,7 +919,7 @@ ex_velocity_grad(MathMatrix vValue[], std::vector > > vvvDeriv[]) { // Get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); + static const TFVGeom& geo = GeomProvider::get(); // reference element typedef typename reference_element_traits::reference_element_type ref_elem_type; @@ -1020,13 +1020,15 @@ template<> void NavierStokesFV1:: register_all_funcs(bool bHang) { + bool bRegisterUsual = true; + // switch assemble functions if(!bHang) { - - // register_func >(); - - register_func > >(); + if ( bRegisterUsual ) + register_func >(); + // else + // register_func > >(); } else { @@ -1040,23 +1042,24 @@ template<> void NavierStokesFV1:: register_all_funcs(bool bHang) { + bool bRegisterUsual = true; + // switch assemble functions if(!bHang) { - - // register_func >(); - // register_func >(); - - register_func > >(); - // register_func > >(); + if ( bRegisterUsual ) + { + register_func >(); + register_func >(); + } + // else + // register_func > >(); } else { UG_THROW("NavierStokesFV1: Hanging Nodes not implemented.") } - } - #endif #ifdef UG_DIM_3 @@ -1064,23 +1067,28 @@ template<> void NavierStokesFV1:: register_all_funcs(bool bHang) { + bool bRegisterUsual = true; + // switch assemble functions if(!bHang) { - /* - register_func >(); - register_func >(); - register_func >(); - register_func >(); - */ - register_func > >(); - - } + if ( bRegisterUsual ) + { + register_func >(); + register_func >(); + register_func >(); + register_func >(); + } + // else + // register_func > >(); + } else { UG_THROW("NavierStokesFV1: Hanging Nodes not implemented.") } + } + #endif template diff --git a/incompressible/fv1/navier_stokes_fv1_FV1.cpp b/incompressible/fv1/navier_stokes_fv1_cutElem.cpp similarity index 89% rename from incompressible/fv1/navier_stokes_fv1_FV1.cpp rename to incompressible/fv1/navier_stokes_fv1_cutElem.cpp index 65db59d..44cbfcc 100644 --- a/incompressible/fv1/navier_stokes_fv1_FV1.cpp +++ b/incompressible/fv1/navier_stokes_fv1_cutElem.cpp @@ -30,17 +30,13 @@ * GNU Lesser General Public License for more details. */ -#include "navier_stokes_fv1.h" +#include "navier_stokes_fv1_cutElem.h" -#include "lib_disc/spatial_disc/disc_util/fv1_geom.h" -//#include "lib_disc/spatial_disc/disc_util/fv1FT_geom.h" +#include "lib_disc/spatial_disc/disc_util/fv1FT_geom.h" #include "lib_disc/spatial_disc/disc_util/geom_provider.h" -//#include "moving_particle/interface_handler_particle.h" namespace ug{ -//template -//class InterfaceHandlerLocalParticle; namespace NavierStokes{ @@ -48,8 +44,9 @@ namespace NavierStokes{ // Constructor - set default values //////////////////////////////////////////////////////////////////////////////// + template -NavierStokesFV1::NavierStokesFV1(const char* functions, +NavierStokesFV1_cutElem::NavierStokesFV1_cutElem(const char* functions, const char* subsets) : IncompressibleNavierStokesBase(functions, subsets) { @@ -57,16 +54,17 @@ NavierStokesFV1::NavierStokesFV1(const char* functions, }; template -NavierStokesFV1::NavierStokesFV1(const std::vector& vFct, +NavierStokesFV1_cutElem::NavierStokesFV1_cutElem(const std::vector& vFct, const std::vector& vSubset) -: IncompressibleNavierStokesBase(vFct, vSubset) +: IncompressibleNavierStokesBase(vFct, vSubset), + m_bCutElemGeom(false) { init(); }; template -void NavierStokesFV1::init() +void NavierStokesFV1_cutElem::init() { // check number of functions if(this->num_fct() != dim+1) @@ -93,7 +91,7 @@ void NavierStokesFV1::init() } template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: prepare_setting(const std::vector& vLfeID, bool bNonRegularGrid) { if(bNonRegularGrid) @@ -108,19 +106,21 @@ prepare_setting(const std::vector& vLfeID, bool bNonRegularGrid) UG_THROW("NavierStokes: 'fv1' expects Lagrange P1 trial space " "for velocity and pressure."); + m_LFEID = vLfeID[0]; + // update assemble functions register_all_funcs(false); } template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: set_kinematic_viscosity(SmartPtr > data) { m_imKinViscosity.set_data(data); } template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: set_density(SmartPtr > data) { m_imDensitySCVF.set_data(data); @@ -128,7 +128,7 @@ set_density(SmartPtr > data) } template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: set_source(SmartPtr, dim> > data) { m_imSourceSCV.set_data(data); @@ -141,7 +141,7 @@ set_source(SmartPtr, dim> > data) template template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: prep_elem_loop(const ReferenceObjectID roid, const int si) { // Only first order implementation @@ -152,16 +152,16 @@ prep_elem_loop(const ReferenceObjectID roid, const int si) // check, that stabilization has been set if(m_spStab.invalid()) UG_THROW("Stabilization has not been set."); - + // init stabilization for element type m_spStab->template set_geometry_type(); - + if (! m_bStokes) // no convective terms in the Stokes eq. => no upwinding { // check, that convective upwinding has been set if(m_spConvStab.invalid() && m_spConvUpwind.invalid()) UG_THROW("Upwinding for convective Term in Momentum eq. not set."); - + // init convection stabilization for element type if(m_spConvStab.valid()) m_spConvStab->template set_geometry_type(); @@ -185,9 +185,10 @@ prep_elem_loop(const ReferenceObjectID roid, const int si) if(!m_imDensitySCV.data_given()) UG_THROW("NavierStokes::prep_elem_loop:" " Density has not been set, but is required."); - + // set local positions for imports - if(!TFVGeom::usesHangingNodes) + //if(!TFVGeom::usesHangingNodes) + if(!TFVGeom::usesHangingNodes && TFVGeom::staticLocalData) { static const int refDim = TElem::dim; TFVGeom& geo = GeomProvider::get(); @@ -201,31 +202,32 @@ prep_elem_loop(const ReferenceObjectID roid, const int si) m_imSourceSCV.template set_local_ips(vSCVip,numSCVip); m_imSourceSCVF.template set_local_ips(vSCVFip,numSCVFip); } - + } + template template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: fsh_elem_loop() {} - template template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: prep_elem(const LocalVector& u, GridObject* elem, ReferenceObjectID roid, const MathVector vCornerCoords[]) { // Update Geometry for this element - TFVGeom& geo = GeomProvider::get(); - try{ + TFVGeom& geo = GeomProvider::get(m_LFEID, 1); + try{ geo.update(elem, vCornerCoords, &(this->subset_handler())); } UG_CATCH_THROW("NavierStokes::prep_elem:" " Cannot update Finite Volume Geometry."); // set local positions for imports - if(TFVGeom::usesHangingNodes) + //if(TFVGeom::usesHangingNodes) + if(TFVGeom::usesHangingNodes || !TFVGeom::staticLocalData) { // request ip series static const int refDim = TElem::dim; @@ -253,16 +255,18 @@ prep_elem(const LocalVector& u, GridObject* elem, ReferenceObjectID roid, const m_imSourceSCVF.set_global_ips(vSCVFip, numSCVFip); } + template template -void NavierStokesFV1:: -add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) +void NavierStokesFV1_cutElem:: +add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, + const MathVector vCornerCoords[]) { // Only first order implementation UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // check for source term to pass to the stabilization const DataImport, dim>* pSource = NULL; @@ -271,6 +275,7 @@ add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat // check for solutions to pass to stabilization in time-dependent case const LocalVector *pSol = &u, *pOldSol = NULL; number dt = 0.0; + if(this->is_time_dependent()) { // get and check current and old solution @@ -286,8 +291,8 @@ add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat } // interpolate velocity at ip with standard lagrange interpolation - static const size_t numSCVF = TFVGeom::numSCVF; -// static const size_t numSCVF = TFVGeom::maxNumSCVF; + //static const size_t numSCVF = TFVGeom::numSCVF; + static const size_t numSCVF = TFVGeom::maxNumSCVF; MathVector StdVel[numSCVF]; for(size_t ip = 0; ip < geo.num_scvf(); ++ip) @@ -604,16 +609,15 @@ add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat template template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) { - //UG_LOG("Anfang add_def_A_elem"); - // Only first order implemented UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + //static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); + TFVGeom& geo = GeomProvider::get(m_LFEID,1); // check for source term to pass to the stabilization const DataImport, dim>* pSource = NULL; @@ -637,9 +641,8 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat } // interpolate velocity at ip with standard lagrange interpolation - - static const size_t numSCVF = TFVGeom::numSCVF; - // static const size_t numSCVF = TFVGeom::maxNumSCVF; + //static const size_t numSCVF = TFVGeom::numSCVF; + static const size_t numSCVF = TFVGeom::maxNumSCVF; MathVector StdVel[numSCVF]; for(size_t ip = 0; ip < geo.num_scvf(); ++ip) @@ -655,20 +658,20 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat // compute stabilized velocities and shapes for continuity equation // \todo: (optional) Here we can skip the computation of shapes, implement? m_spStab->update(&geo, *pSol, StdVel, m_bStokes, m_imKinViscosity, m_imDensitySCVF, pSource, pOldSol, dt); - + if (! m_bStokes) // no convective terms in the Stokes eq. => no upwinding { // compute stabilized velocities and shapes for convection upwind if(m_spConvStab.valid()) if(m_spConvStab != m_spStab) m_spConvStab->update(&geo, *pSol, StdVel, false, m_imKinViscosity, m_imDensitySCVF, pSource, pOldSol, dt); - + // compute upwind shapes if(m_spConvUpwind.valid()) if(m_spStab->upwind() != m_spConvUpwind) m_spConvUpwind->update(&geo, StdVel); } - + // get a const (!!) reference to the stabilization const INavierStokesFV1Stabilization& stab = *m_spStab; const INavierStokesFV1Stabilization& convStab = *m_spConvStab; @@ -702,10 +705,9 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat gradVel(d1, d2) = 0.0; for(size_t sh = 0; sh < scvf.num_sh(); ++sh) gradVel(d1, d2) += scvf.global_grad(sh)[d2] - * u(d1, sh); + * u(d1, sh); } - // 2. Compute flux MathVector diffFlux; @@ -725,7 +727,7 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat d(d1, scvf.from()) += diffFlux[d1]; d(d1, scvf.to() ) -= diffFlux[d1]; } - + //////////////////////////////////////////////////// // Convective Term (Momentum Equation) //////////////////////////////////////////////////// @@ -738,15 +740,15 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat // find the upwind velocity at ip MathVector UpwindVel; - // switch PAC - if(m_spConvUpwind.valid()) UpwindVel = upwind.upwind_vel(ip, u, StdVel); - else if (m_spConvStab.valid()) UpwindVel = convStab.stab_vel(ip); - else UG_THROW("Cannot find upwind for convective term."); - + // switch PAC + if(m_spConvUpwind.valid()) UpwindVel = upwind.upwind_vel(ip, u, StdVel); + else if (m_spConvStab.valid()) UpwindVel = convStab.stab_vel(ip); + else UG_THROW("Cannot find upwind for convective term."); + // Peclet Blend if(m_bPecletBlend) peclet_blend(UpwindVel, geo, ip, StdVel[ip], m_imKinViscosity[ip]); - + // compute product of standard velocity and normal const number prod = VecProd(StdVel[ip], scvf.normal()) * m_imDensitySCVF[ip]; @@ -756,8 +758,9 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat d(d1, scvf.from()) += UpwindVel[d1] * prod; d(d1, scvf.to() ) -= UpwindVel[d1] * prod; } + } - + //////////////////////////////////////////////////// // Pressure Term (Momentum Equation) //////////////////////////////////////////////////// @@ -774,6 +777,7 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat d(d1, scvf.to() ) -= pressure * scvf.normal()[d1]; } + //////////////////////////////////////////////////// //////////////////////////////////////////////////// // Continuity Equation (conservation of mass) @@ -786,20 +790,22 @@ add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat // Add contributions to local defect d(_P_, scvf.from()) += contFlux; d(_P_, scvf.to() ) -= contFlux; - } + + } + } template template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) { // Only first order implementation UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) @@ -822,14 +828,14 @@ add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const Mat template template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]) { // Only first order implementation UG_ASSERT((TFVGeom::order == 1), "Only first order implemented."); // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) @@ -852,7 +858,7 @@ add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const Mat template template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoords[]) { // Only first order implementation @@ -862,7 +868,7 @@ add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoor if(!m_imSourceSCV.data_given()) return; // get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // loop Sub Control Volumes (SCV) for(size_t ip = 0; ip < geo.num_scv(); ++ip) @@ -884,7 +890,7 @@ template template inline number -NavierStokesFV1:: +NavierStokesFV1_cutElem:: peclet_blend(MathVector& UpwindVel, const TFVGeom& geo, size_t ip, const MathVector& StdVel, number kinVisco) { @@ -906,7 +912,7 @@ peclet_blend(MathVector& UpwindVel, const TFVGeom& geo, size_t ip, // computes the linearized defect w.r.t to the velocity template template -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: ex_velocity_grad(MathMatrix vValue[], const MathVector vGlobIP[], number time, int si, @@ -919,7 +925,7 @@ ex_velocity_grad(MathMatrix vValue[], std::vector > > vvvDeriv[]) { // Get finite volume geometry - static const TFVGeom& geo = GeomProvider::get(); + static const TFVGeom& geo = GeomProvider::get(m_LFEID, 1); // reference element typedef typename reference_element_traits::reference_element_type ref_elem_type; @@ -1017,84 +1023,76 @@ ex_velocity_grad(MathMatrix vValue[], #ifdef UG_DIM_1 template<> -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: register_all_funcs(bool bHang) { - bool bRegisterUsual = true; - // switch assemble functions if(!bHang) { - if ( bRegisterUsual ) - register_func >(); - // else - // register_func > >(); + + // register_func >(); + + register_func > >(); } else { - UG_THROW("NavierStokesFV1: Hanging Nodes not implemented.") + UG_THROW("NavierStokesFV1_cutElem: Hanging Nodes not implemented.") } } #endif #ifdef UG_DIM_2 template<> -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: register_all_funcs(bool bHang) { - bool bRegisterUsual = true; - // switch assemble functions if(!bHang) { - if ( bRegisterUsual ) - { - register_func >(); - register_func >(); - } - // else - // register_func > >(); + + // register_func >(); + // register_func >(); + + register_func > >(); + // register_func > >(); } else { - UG_THROW("NavierStokesFV1: Hanging Nodes not implemented.") + UG_THROW("NavierStokesFV1_cutElem: Hanging Nodes not implemented.") } + } + #endif #ifdef UG_DIM_3 template<> -void NavierStokesFV1:: +void NavierStokesFV1_cutElem:: register_all_funcs(bool bHang) { - bool bRegisterUsual = true; - // switch assemble functions if(!bHang) { - if ( bRegisterUsual ) - { - register_func >(); - register_func >(); - register_func >(); - register_func >(); - } - // else - // register_func > >(); - } + /* + register_func >(); + register_func >(); + register_func >(); + register_func >(); + */ + register_func > >(); + + } else { - UG_THROW("NavierStokesFV1: Hanging Nodes not implemented.") + UG_THROW("NavierStokesFV1_cutElem: Hanging Nodes not implemented.") } - } - #endif template template void -NavierStokesFV1:: +NavierStokesFV1_cutElem:: register_func() { ReferenceObjectID id = geometry_traits::REFERENCE_OBJECT_ID; @@ -1120,10 +1118,10 @@ register_func() //////////////////////////////////////////////////////////////////////////////// #ifdef UG_DIM_2 -template class NavierStokesFV1; +template class NavierStokesFV1_cutElem; #endif #ifdef UG_DIM_3 -template class NavierStokesFV1; +template class NavierStokesFV1_cutElem; #endif } // namespace NavierStokes diff --git a/incompressible/fv1/navier_stokes_fv1_cutElem.h b/incompressible/fv1/navier_stokes_fv1_cutElem.h new file mode 100644 index 0000000..97a2c91 --- /dev/null +++ b/incompressible/fv1/navier_stokes_fv1_cutElem.h @@ -0,0 +1,587 @@ +/* + * Copyright (c) 2010-2014: G-CSC, Goethe University Frankfurt + * Author: Andreas Vogel + * + * This file is part of UG4. + * + * UG4 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License version 3 (as published by the + * Free Software Foundation) with the following additional attribution + * requirements (according to LGPL/GPL v3 §7): + * + * (1) The following notice must be displayed in the Appropriate Legal Notices + * of covered and combined works: "Based on UG4 (www.ug4.org/license)". + * + * (2) The following notice must be displayed at a prominent place in the + * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". + * + * (3) The following bibliography is recommended for citation and must be + * preserved in all covered files: + * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively + * parallel geometric multigrid solver on hierarchically distributed grids. + * Computing and visualization in science 16, 4 (2013), 151-164" + * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel + * flexible software system for simulating pde based models on high performance + * computers. Computing and visualization in science 16, 4 (2013), 165-179" + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + + +#ifndef __H__UG__PLUGINS__NAVIER_STOKES__INCOMPRESSIBLE__FV1__NAVIER_STOKES_FV1_CUT_ELEM_ +#define __H__UG__PLUGINS__NAVIER_STOKES__INCOMPRESSIBLE__FV1__NAVIER_STOKES_FV1_CUT_ELEM_ + +// other ug4 modules +#include "common/common.h" +#include "lib_grid/lg_base.h" + +// library intern headers +#include "lib_disc/spatial_disc/elem_disc/elem_disc_interface.h" +#include "lib_disc/spatial_disc/user_data/data_export.h" +#include "lib_disc/spatial_disc/user_data/data_import.h" + +#include "../incompressible_navier_stokes_base.h" +#include "../../upwind_interface.h" +#include "stabilization.h" + +namespace ug{ + +namespace NavierStokes{ + + +/// \ingroup lib_disc_elem_disc +/// @{ + +/// Finite Volume Element Discretization for the incompressible Navier-Stokes Equation +/** + * This class implements the IElemDisc interface to provide element local + * assemblings for the incompressible Navier-Stokes equation. + * + * The unknowns of the equation are: + *
    + *
  • \f$ \vec{u} \f$ velocity + *
  • \f$ p \f$ pressure. + *
+ * + * The equation takes the form + * \f{align*} + * \frac{\partial \rho \vec{u}}{\partial t} + * - \nabla \left( \rho \nu (\nabla \vec{u} + (\nabla \vec{u})^T) \right) + * + \nabla \cdot \left( \rho \vec{u} \vec{u}^T \right) + * + \nabla p + * &= \vec{f}\\ + * + * \nabla \cdot (\rho \vec{u}) &= 0 + * \f} + * + * with + *
    + *
  • \f$ \rho \f$ is the constant density + *
  • \f$ \nu \f$ is the kinematic viscosity (temporarily constant, implement) + *
  • \f$ \vec{f} \equiv f(\vec{x},t) \f$ is a Source Term (not implemented yet) + *
+ * + * The first equation models the conservation of momentum and is therefore + * referred to as the Momentum equation. The second equation models the + * conservation of mass and is known as the Mass continuity equation or + * simply Continuity equation. + * + * In component-wise notation, the equation reads + * + * \f{align*} + * \frac{\partial \rho u_{d_1}}{\partial t} + * - \sum_{d_2 = 1}^{\text{dim}} \frac{\partial}{\partial x_{d_2}} + * \left( \rho \nu \left( \frac{\partial u_{d_1}}{\partial x_{d_2}} + * + \frac{\partial u_{d_2}}{\partial x_{d_1}} \right)\right) + * + \sum_{d_2 = 1}^{\text{dim}} \frac{\partial}{\partial x_{d_2}} + * \left( \rho u_{d_2} u_{d_1} \right) + * + \frac{\partial p}{\partial x_{d_1}} + * &= f_{d_1} \qquad \forall \quad d_1 = 1, \dots, \text{dim}\\ + * + * \sum_{d = 1}^{\text{dim}} \frac{\partial \rho u_d}{\partial x_{d}} &= 0 + * \f} + * + * Since the density is assumed to be constant, it set to \f$\rho \equiv 1 \f$. + * + * The finite volume element discretization uses a dual mesh consisting of + * Control Volumes \f$\mathcal{B}_h\f$, that cover the domain. For each + * control volume \f$B \in \mathcal{B}_h\f$ the following equation is solved + * + * \f{align*} + * \frac{\partial}{\partial t} \int_{B} \begin{pmatrix} \vec{u} \\ 0 \end{pmatrix} dV + * + \int_{\partial B} + * \begin{pmatrix} + * - \rho \nu \left(\nabla \vec{u} + (\nabla \vec{u})^T \right) \vec{n} + * + \vec{u} \vec{u}^T \vec{n} + p \vec{n} \\ + * \vec{u} \vec{n} + * \end{pmatrix} dS + * = \int_B \begin{pmatrix} \vec{f} \\ 0 \end{pmatrix} dV + * \f} + * + * where \f$ \vec{n}\f$ is the outer normal on the boundary of the control volume + * and \f$\int_B \cdot \; dV \f$ and \f$\int_{\partial B} \cdot \; dS \f$ are the + * integration over the control volume and the integration over the boundary of + * the control volume. By \$f B_{sh} \$f is denoted the control volume associated + * to a shape function (i.e. vertices, since we use P1 Lagrange ansatz functions), + * T usually denotes the Element. + * + * In order to number the local unknowns, we use the following notation. + *
    + *
  • \f$ sh = 0, \dots, n_{sh} - 1\f$ loop the \f$n_{sh}\f$ shape functions. For + * this implementation these are the corners of the element + *
  • \f$ d = 0, \dots, \text{dim} - 1 \f$ are the velocity component of each + * corner + *
  • _P_ := dim indicates the pressure component + *
+ * The access to local unknowns of local vectors and matrices is now given by + * \f{align*} + * &\mathbf{d}(d_1, sh), \mathbf{d}(\text{\_P\_}, sh),\\ + * &\mathcal{J}(d_1, sh_1, d_2, sh_2), \mathcal{J}(d_1, sh_1, \text{\_P\_}, sh_2), + * \f} + * + * \tparam TDomain Domain + * \tparam TAlgebra Algebra + */ +template< typename TDomain> +class NavierStokesFV1_cutElem + : public IncompressibleNavierStokesBase +{ + protected: + /// Base class type + typedef IncompressibleNavierStokesBase base_type; + + /// own type + typedef NavierStokesFV1_cutElem this_type; + + public: + /// World dimension + static const int dim = base_type::dim; + + public: + /// Constructor (setting default values) + /// \{ + NavierStokesFV1_cutElem(const char* functions, const char* subsets); + NavierStokesFV1_cutElem(const std::vector& vFct, const std::vector& vSubset); + /// \} + + /// sets the kinematic viscosity + void set_kinematic_viscosity(SmartPtr > user); + + /// returns kinematic viscosity + SmartPtr > kinematic_viscosity() {return m_imKinViscosity.user_data ();} + + /// sets the density + void set_density(SmartPtr > user); + + /// returns density + SmartPtr > density() {return m_imDensitySCVF.user_data ();} + + /// sets the source function + void set_source(SmartPtr, dim> > user); + + /// returns scvf source + DataImport, dim> sourceSCVF(){ return m_imSourceSCVF;} + + /// sets the stabilization used to compute the stabilized velocities + void set_stabilization(SmartPtr > spStab) + {m_spStab = spStab;} + + /// sets stabilization based on string identifier + void set_stabilization(const std::string& name) + {m_spStab = CreateNavierStokesStabilization(name); + if(m_spConvUpwind.valid()) m_spStab->set_upwind(m_spConvUpwind);} + + /// sets stabilization and diff length method based on string identifier (only for Schneider-Raw stabilizations) + void set_stabilization(const std::string& name, const std::string& diffLength) + {SmartPtr > spStab = CreateNavierStokesStabilization(name); + spStab->set_diffusion_length(diffLength); + m_spStab = spStab; + if(m_spConvUpwind.valid()) m_spStab->set_upwind(m_spConvUpwind);} + + /// returns stabilization + SmartPtr > stabilization(){ return m_spStab;} + + /// sets a stabilization for upwinding (Physical Advection Correction) + void set_upwind(SmartPtr > spStab) + {m_spConvStab = spStab; m_spConvUpwind = SPNULL;} + + /// sets an upwinding for the convective term of momentum equation + void set_upwind(SmartPtr > spUpwind) + {m_spConvStab = SPNULL; m_spConvUpwind = spUpwind;} + + /// sets the upwind based on a string identifier + void set_upwind(const std::string& name) + {m_spConvStab = SPNULL; m_spConvUpwind = CreateNavierStokesUpwind(name); + if(m_spStab.valid() && m_spStab->upwind().invalid()) m_spStab->set_upwind(m_spConvUpwind);} + + void set_pac_upwind(bool bPac) + { + if (bPac==true){ + if (m_spConvUpwind.valid()) m_spStab->set_upwind(m_spConvUpwind); + else UG_THROW("Upwind must be specified previously.\n"); + if (m_spStab.valid()) set_upwind(m_spStab); + else UG_THROW("Stabilization must be specified previously.\n"); + } + } + + protected: + /// computes the value of the gradient of the pressure + template + void ex_velocity_grad(MathMatrix vValue[], + const MathVector vGlobIP[], + number time, int si, + const LocalVector& u, + GridObject* elem, + const MathVector vCornerCoords[], + const MathVector vLocIP[], + const size_t nip, + bool bDeriv, + std::vector > > vvvDeriv[]); + + using base_type::m_exVelocityGrad; + + public: + /// type of trial space for each function used + virtual void prepare_setting(const std::vector& vLfeID, bool bNonRegularGrid); + + /// returns string identifying disc type + virtual std::string disc_type() const {return "fv1";}; + + public: + /// prepares the element loop + /** + * This function is used to prepare the element loop. It gets called, before + * the loop over all elements starts. Here, general checks are performed: + * - Is the correct finite volume geometry used + * - Has the stabilization been specified + * + * In addition, local coordinates of evaluation points are requested by + * the DataImports in case of element-fixed points. + */ + template + void prep_elem_loop(const ReferenceObjectID roid, const int si); + + /// prepares the element for evaluation + /** + * This function prepare a specific element for assembling. This function + * is always called before any of the assemble_... functions is performed. + * Here, the Finite Volume Geometry is prepared and global positions of + * the evaluation points of the DataImports are requested (and local + * positions in case of hanging node assembling) + * + * \param[in] elem element to prepare the data for + * \param[in] u current local solution vector + * \param[in] glob_ind global indices of the local vector components + */ + template + void prep_elem(const LocalVector& u, GridObject* elem, const ReferenceObjectID roid, const MathVector vCornerCoords[]); + + /// finishes the element loop + template + void fsh_elem_loop(); + + /// adds the stiffness part to the local jacobian + /** + * This function adds the local contributions of the stiffness part to + * the local jacobian. + * + * For the definition of \f$ \vec{f}^{\text{diff}}|_{ip}\f$ and + * \f$ \vec{f}^{\text{conv}}|_{ip}\f$ see add_def_A_elem. + * + * The derivative of the diffusive flux is given by + * \f{align*} + * \frac{\partial \vec{f}^{\text{diff}}_{d_1}|_{ip}}{\partial \vec{u}_{d_2}^{sh}} + * &= - \nu \left( \delta_{d_1, d_2} \sum_{k=1}^{\text{dim}} + * \left. \frac{\partial \phi^{sh}}{\partial x_k}\right|_{ip} \vec{n_k}|_{ip} + * + \left. \frac{\partial \phi^{sh}}{\partial x_{d_1}}\right|_{ip} \vec{n_{d_2}}|_{ip} + * \right)\\ + * \frac{\partial \vec{f}^{\text{diff}}_{d_1}|_{ip}}{\partial p^{sh}} + * &= 0 + * \f} + * + * For the derivative of the convective term, we can use a fixpoint linearization + * if we only differentiate the first factor of + * \f$ + * \vec{f}^{\text{conv}}_{d_1} + * = (\vec{u}^{\text{blend}} (\vec{u}^{\text{blend}})^T)_{d_1 k} \vec{n}_k + * = \vec{u}^{\text{blend}}_{d_1} \sum_{k=1}^{\text{dim}} \vec{u}^{\text{blend}}_k \vec{n}_k + * = \vec{u}^{\text{blend}}_{d_1} \langle \vec{u}^{\text{blend}}, \vec{n} \rangle + * \f$ + * + * This gives + * \f{align*} + * \frac{\partial \vec{f}^{\text{conv}}_{d_1}}{\partial \vec{u}_{d_2}^{sh}} + * &= \langle \vec{u}^{\text{blend}}, \vec{n} \rangle + * \frac{\partial \vec{u}^{\text{blend}}_{d_1}}{\partial \vec{u}_{d_2}^{sh}} + * &= \langle \vec{u}^{\text{blend}}, \vec{n} \rangle \left( + * (1-\omega) \delta_{d_1 d_2} \phi^{sh} + * + \omega \frac{\partial \vec{u}^{\text{up}}_{d_1}}{\partial \vec{u}_{d_2}^{sh}} + * \right) + * \f} + * + * The derivative of the pressure term is given by + * \f{align*} + * \frac{\partial p \vec{n}|_{ip}}{\partial \vec{u}_{d_2}^{sh}} + * &= 0\\ + * \frac{\partial p \vec{n}|_{ip}}{\partial p^{sh}} + * &= \phi^{sh}|_{ip} \vec{n} + * \f} + * + * The derivative of the continuity term is given by + * \f{align*} + * \frac{\partial \vec{u}^{\text{stab}}|_{ip} \vec{n}|_{ip}}{\partial \vec{u}_{d_1}^{sh}} + * &= \sum_{d_2=1}^{dim} \left. \frac{\partial u_{d_2}^{\text{stab}}} + * {\partial \vec{u}_{d_1}^{sh}} \right|_{ip} \vec{n}_{d_2}\\ + * \frac{\partial \vec{u}^{\text{stab}}|_{ip} \vec{n}|_{ip}}{\partial p^{sh}} + * &=\sum_{d_2=1}^{dim} \left. \frac{\partial u_{d_2}^{\text{stab}}} + * {\partial p^{sh}} \right|_{ip} \vec{n}_{d_2}\\ + * \f} + * + * \param[in,out] J local jacobian with values added on output + * \param[in] u local vector of current solution + * \param[in] time current time step + * + * \tparam TElem Element type + * \tparam TFVGeom Finite Volume Geometry + */ + template + void add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]); + + /// adds the stiffness part to the local defect + /** + * This function adds the contribution of one element of the stiffness part to + * the local defect. + * + * The local solution \f$ \mathbf{u} \f$ passes the p1 conform lagrange + * dofs of the element, i.e. the unknowns in the corners of the element. + * + * Define the functional matrix of the velocity at some integration point by + * \f{align*} + * \nabla \vec{u}|_{ip} := \left(\left.\frac{\partial u_i}{\partial x_j} + * \right|_{ip}\right)_{i,j = 1,\dots,dim} + * \f} + * + * and the diffusive flux to + * \f{align*} + * \vec{f}^{\text{diff}}|_{ip} := - \nu \left( \nabla \vec{u}|_{ip} + + * (\nabla \vec{u}|_{ip})^T) \right) \cdot \vec{n}_{ip} + * \f} + * + * Suppose that a procedure producing some upwind velocity \f$ \vec{u}^{up}\f$ + * is available for each ip. Then, we define the convective flux to + * \f{align*} + * \vec{f}^{\text{conv}}|_{ip} := \left( \vec{u}^{up}|_{ip} \vec{u}^{up}|_{ip}^T + * \right) \cdot \vec{n}_{ip} + * \f} + * + * Define the pressure at the ip to be interpolated as + * \f{align*} + * p|_{ip} := \sum_{sh=0}^{n_{sh}-1} \mathbf{u}(\text{\_P\_}, sh) \phi_{sh} + * \f} + * + * The contribution added for the momentum equation is: + * \f{align*} + * \forall d=0,\dots, \text{dim}-1, \quad + * \forall sh=0,\dots, n_{sh}-1: \qquad + * \mathbf{d}(d, sh) &\text{ +=} + * \int_{\partial B_{sh} \cap T} \vec{f}^{\text{diff}}_d + * + \vec{f}^{\text{conv}}_d + * + p \vec{n}_d \;dS + * + * \approx \sum_{i=1}^{n_{\partial B_{sh}}} + * |\partial B^i_{sh} \cap T| + * \left( \left.\vec{f}^{\text{diff}}_d\right|_{ip} + * + \left.\vec{f}^{\text{conv}}_d\right|_{ip} + * + p|_{ip} \vec{n}|_{ip} \right)\\ + * \f} + * + * Assume, that some stabilized velocity \f$ \vec{u}^{stab}\f$ is available + * for each ip. + * Then, the contribution added for the continuity equation is: + * \f{align*} + * \forall sh=0,\dots, n_{sh}-1: \qquad + * \mathbf{d}(\text{\_P\_}, sh) &\text{ +=} + * \int_{\partial B_{sh} \cap T} \vec{u}^{stab} \cdot \vec{n} \;dS + * + * \approx \sum_{i=1}^{n_{\partial B_{sh}}} + * |\partial B^i_{sh} \cap T| \; \vec{u}^{stab}|_{ip} \cdot \vec{n}|_{ip}\\ + * \f} + * + * \param[in,out] d local defect with values added on output + * \param[in] u local vector of current solution + * \param[in] time current time step + * + * \tparam TElem Element type + * \tparam TFVGeom Finite Volume Geometry + */ + template + void add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]); + + /// adds the mass part to the local jacobian + /** + * This function adds the contribution of one element of the mass part to + * the local jacobian. + * + * The local solution \f$ \mathbf{u} \f$ passes the p1 conform lagrange + * dofs of the element, i.e. the unknowns in the corners of the element. + * + * The contribution added is: + * \f{align*} + * \forall d=0,\dots, \text{dim}-1, \quad + * \forall sh=0,\dots, n_{sh}-1: \qquad + * \mathcal{J}(d, sh, d, sh) &\text{ +=} \int_{B_{sh} \cap T} dV + * = |B_{sh} \cap T|\\ + * \f} + * + * \param[in,out] J local jacobian with values added on output + * \param[in] u local vector of current solution + * \param[in] time current time step + * + * \tparam TElem Element type + * \tparam TFVGeom Finite Volume Geometry + */ + template + void add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]); + + /// adds the mass part to the local defect + /** + * This function adds the contribution of one element of the mass part to + * the local defect. + * + * The local solution \f$ \mathbf{u} \f$ passes the p1 conform lagrange + * dofs of the element, i.e. the unknowns in the corners of the element. + * + * The contribution added is: + * \f{align*} + * \forall d=0,\dots, \text{dim}-1, \quad + * \forall sh=0,\dots, n_{sh}-1: \qquad + * \mathbf{d}(d, sh) &\text{ +=} \int_{B_{sh} \cap T} \vec{u}_d dV + * \approx |B_{sh} \cap T| \mathbf{u}(d, sh)\\ + * + * \mathbf{d}(\text{\_P\_, sh}) &\text{ +=} 0 + * \f} + * + * \param[in,out] d local defect with values added on output + * \param[in] u local vector of current solution + * \param[in] time current time step + * + * \tparam TElem Element type + * \tparam TFVGeom Finite Volume Geometry + */ + template + void add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector vCornerCoords[]); + + /// adds the source part to the local defect + /** + * This function adds the contribution of one element of the source part to + * the local defect, if a source function \f$ \vec{f} \f$ has been specified. + * Otherwise a zero source function is assumed. + * + * The contribution added is: + * \f{align*} + * \forall d=0,\dots, \text{dim}-1, \quad + * \forall sh=0,\dots, n_{sh}-1: \qquad + * \mathbf{d}(d, sh) &\text{ +=} \int_{B_{sh} \cap T} \vec{f}_d \; dV + * \approx |B_{sh} \cap T| \; \vec{f}_d|_{ip} + * \f} + * + * \param[in,out] d local defect with values added on output + * \param[in] time current time step + * + * \tparam TElem Element type + * \tparam TFVGeom Finite Volume Geometry + */ + template + void add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector vCornerCoords[]); + + /// computes the pecled blended Upwind veloctity + /** + * This function compute the peclet blended velocity. First, the + * standard interpolated (no upwind) velocity is computed at the integration + * point of the scvf: + * \f{align*} + * \vec{u}^{\text{std}}_d|_{ip} + * := \sum_{sh=0}^{n_{sh}-1} \mathbf{u}(d, sh) \; \phi_{sh} + * \f} + * + * Defining the Peclet Number + * \f{align*} + * Pe := \frac{\vec{u}^{\text{std}}|_{ip} \cdot \vec{n}|_{ip} \; L}{\nu} + * \f} + * with the Viscosity \f$ \nu \f$ and the diffusion length \f$ L \f$, a + * weighting factor is computed: + * \f{align*} + * \omega := \frac{Pe^2}{5 + Pe^2} + * \f} + * + * and the blended velocity is computed to + * \f{align*} + * \vec{u}^{\text{blend}}|_{ip} := \omega \vec{u}^{\text{up}} + * + (1-\omega) \vec{u}^{\text{std}} + * \f} + * + * \param[in,out] UpwindVel upwind vel on entry, blended vel on exit + * \param[in] scvf SubControlVolumeFace of the Velocity + * \param[in] StdVel standard interpolation vel + * \param[in] kinVisco kinematic Viscosity at scvf + * \return \f$\omega\f$ weighting factor + */ + template + inline number peclet_blend(MathVector& UpwindVel, const TFVGeom& geo, size_t ip, + const MathVector& StdVel, number kinVisco); + + protected: + /// Data import for source + DataImport, dim> m_imSourceSCV; + DataImport, dim> m_imSourceSCVF; + + /// Data import for kinematic viscosity + DataImport m_imKinViscosity; + + /// Data import for density + DataImport m_imDensitySCVF; + DataImport m_imDensitySCV; + + /// Stabilization for velocity in continuity equation + SmartPtr > m_spStab; + + /// Stabilization for velocity in convective term of momentum equation + /// Here, the stabilization is used as an upwinding + SmartPtr > m_spConvStab; + + /// Upwinding for velocity in convective term of momentum equation + SmartPtr > m_spConvUpwind; + + /// abbreviation for pressure + static const size_t _P_ = dim; + + using base_type::m_bPecletBlend; + using base_type::m_bFullNewtonFactor; + using base_type::m_bStokes; + using base_type::m_bLaplace; + + virtual void init(); + + protected: + /// current shape function set (needed for GeomProvider::get()) + LFEID m_LFEID; + + /// flag for moving particle discretisation + bool m_bCutElemGeom; + + /// register utils + /// \{ + virtual void register_all_funcs(bool bHang); + template void register_func(); + /// \} +}; + +/// @} + +} // namespace NavierStokes +} // end namespace ug + +#endif /*__H__UG__PLUGINS__NAVIER_STOKES__INCOMPRESSIBLE__FV1__NAVIER_STOKES_FV1_CUT_ELEM_*/ diff --git a/incompressible/fv1/register_fv1.cpp b/incompressible/fv1/register_fv1.cpp index f800258..0787e09 100644 --- a/incompressible/fv1/register_fv1.cpp +++ b/incompressible/fv1/register_fv1.cpp @@ -35,6 +35,9 @@ #include "bridge/util_domain_algebra_dependent.h" #include "navier_stokes_fv1.h" +#include "navier_stokes_fv1_cutElem.h" +#include "bnd/inflow_fv1_cutElem.h" + #include "bnd/inflow_fv1.h" #include "bnd/no_normal_stress_outflow_fv1.h" #include "bnd/symmetric_boundary_fv1.h" @@ -85,6 +88,17 @@ static void DomainAlgebra(Registry& reg, string grp) reg.add_class_to_group(name, "NavierStokesInflowFV1", tag); } + // NavierStokesInflow FV1 cutElem + { + typedef NavierStokesInflowFV1_cutElem T; + typedef NavierStokesInflowBase TBase; + string name = string("NavierStokesInflowFV1_cutElem").append(suffix); + reg.add_class_(name, grp) + .template add_constructor >)>("MasterElemDisc") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "NavierStokesInflowFV1_cutElem", tag); + } + typedef ug::GridFunction TFct; static const int dim = TDomain::dim; @@ -163,12 +177,32 @@ static void Domain(Registry& reg, string grp) static const int dim = TDomain::dim; string suffix = GetDomainSuffix(); string tag = GetDomainTag(); - - // Navier-Stokes FV1 + + // Navier-Stokes FV1 + { + typedef NavierStokesFV1 T; + typedef IncompressibleNavierStokesBase TBase; + string name = string("NavierStokesFV1").append(suffix); + reg.add_class_(name, grp) + .template add_constructor("Functions#Subset(s)") + .template add_constructor&, const std::vector&)>("Functions#Subset(s)") + .add_method("set_stabilization", static_cast >)>(&T::set_stabilization)) + .add_method("set_stabilization", static_cast(&T::set_stabilization)) + .add_method("set_stabilization", static_cast(&T::set_stabilization)) + .add_method("set_upwind", static_cast >)>(&T::set_upwind)) + .add_method("set_upwind", static_cast >)>(&T::set_upwind)) + .add_method("set_upwind", static_cast(&T::set_upwind)) + .add_method("set_pac_upwind", &T::set_pac_upwind, "", "Set pac upwind") + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "NavierStokesFV1", tag); + } + + + // Navier-Stokes FV1_cutElem { - typedef NavierStokesFV1 T; + typedef NavierStokesFV1_cutElem T; typedef IncompressibleNavierStokesBase TBase; - string name = string("NavierStokesFV1").append(suffix); + string name = string("NavierStokesFV1_cutElem").append(suffix); reg.add_class_(name, grp) .template add_constructor("Functions#Subset(s)") .template add_constructor&, const std::vector&)>("Functions#Subset(s)") @@ -179,8 +213,8 @@ static void Domain(Registry& reg, string grp) .add_method("set_upwind", static_cast >)>(&T::set_upwind)) .add_method("set_upwind", static_cast(&T::set_upwind)) .add_method("set_pac_upwind", &T::set_pac_upwind, "", "Set pac upwind") - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "NavierStokesFV1", tag); + .set_construct_as_smart_pointer(true); + reg.add_class_to_group(name, "NavierStokesFV1_cutElem", tag); } diff --git a/incompressible/fv1/stabilization.h b/incompressible/fv1/stabilization.h index 8444123..266fd00 100644 --- a/incompressible/fv1/stabilization.h +++ b/incompressible/fv1/stabilization.h @@ -123,8 +123,8 @@ class INavierStokesFV1Stabilization else { // hard code as !maxNum, since maybe crash, e.g. in update() for computation of mat!! - m_numScvf = TFVGeom::maxNumSCVF; // changed on march 2019! before it was: dim+2; // TFVGeom::maxNumSCVF; - m_numSh = TFVGeom::maxNSH;; // changed on march 2019! before it was: dim+2; // TFVGeom::maxNSH; + m_numScvf = traits::maxNumSCVF; + m_numSh = traits::maxNSH; } // set sizes in upwind diff --git a/incompressible/fv1/two_phase_flow/interface_handler_2pf.h b/incompressible/fv1/two_phase_flow/interface_handler_2pf.h index 42779f2..4ccc5bc 100644 --- a/incompressible/fv1/two_phase_flow/interface_handler_2pf.h +++ b/incompressible/fv1/two_phase_flow/interface_handler_2pf.h @@ -28,7 +28,7 @@ class InterfaceHandlerLocal2PF : public InterfaceHandlerLocalDiffusion::grid_base_object grid_base_object; InterfaceHandlerLocal2PF(SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler, + SmartPtr > cutElementHandler, number fluidDensity, number fluidKinVisc); virtual ~InterfaceHandlerLocal2PF() {} @@ -95,10 +95,7 @@ class InterfaceHandlerLocal2PF : public InterfaceHandlerLocalDiffusion sourceIm, LocalIndices ind, const size_t size, const bool bElementIsCut) - {LocalVector dummy; return dummy;} - LocalVector set_source(LocalIndices ind, const size_t size, const bool bElementIsCut); - + double get_jump_value_const(const MathVector position); double get_jump_value(const MathVector position); double get_jump_value_ex3(const MathVector position); @@ -109,7 +106,7 @@ class InterfaceHandlerLocal2PF : public InterfaceHandlerLocalDiffusion position); // writes solution of global vector vec into this->m_verticesValue-array: - void write_solution(const std::vector verticesValues); + void set_interface_values(const std::vector verticesValues); void resize_local_data(LocalVector locU) @@ -144,12 +141,12 @@ class InterfaceHandlerLocal2PF : public InterfaceHandlerLocalDiffusion InterfaceHandlerLocal2PF::InterfaceHandlerLocal2PF( SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler, + SmartPtr > cutElementHandler, number fluidDensity, number fluidKinVisc) : InterfaceHandlerLocalDiffusion(interfaceProvider, cutElementHandler), m_fluidDensity(fluidDensity), @@ -35,7 +35,7 @@ InterfaceHandlerLocal2PF::InterfaceHandlerLocal2PF( template void InterfaceHandlerLocal2PF:: -write_solution(const std::vector verticesValues) +set_interface_values(const std::vector verticesValues) { this->m_verticesValue.clear(); @@ -48,7 +48,7 @@ write_solution(const std::vector verticesValues) { UG_LOG("m_verticesValue.size(): " << this->m_verticesValue.size() << "\n"); UG_LOG("verticesValues.size(): " << verticesValues.size() << "\n"); - UG_THROW("in InterfaceHandlerLocal2PF::write_solution: wrong size of m_verticesValue!\n"); + UG_THROW("in InterfaceHandlerLocal2PF::set_interface_values: wrong size of m_verticesValue!\n"); } } @@ -230,45 +230,6 @@ get_source(const MathVector position) return 2.0; //returnValue; } -template -LocalVector InterfaceHandlerLocal2PF:: -set_source(LocalIndices ind, const size_t size, const bool bElementIsCut) -{ - LocalVector source; - ind.resize_dof(0, size); - source.resize(ind); - -// loop and set solution in 'solU_tri': - for (size_t dof = 0; dof < source.num_all_dof(0); ++dof) - { -/* if ( dof > 2 ) - source.value(0, dof) = sourceIm[2]; // done during 'add_def_elem_local()' - else - source.value(0, dof) = sourceIm[dof]; // done during 'add_def_elem_local()' -*/ - - - // if dof_real is index of m_vertex: get solution from class: - if ( this->lies_onInterface_size(dof, size) ) - { - size_t dof_real = this->real_index_size(dof, size); - source.value(0, dof) = get_source_kappa(this->get_VerticesPos(dof_real)); - } - else - { -/* - size_t dof_orig = this->corner_orig(dof); - source.value(0, dof) = sourceIm[dof_orig]; // done during 'add_def_elem_local()' -*/ - // careful: this->corner() returns corner coords of new corners => use dof-Index, NOT dof_orig-Index?! - source.value(0, dof) = get_source_kappa(this->corner(dof)); - - } - - } - - return source; -} template @@ -382,7 +343,7 @@ CollectCorners_FlatTop_2d(GridObject* elem) for(size_t i = 0; i < vVertex.size(); ++i) { // remember boolian for check, weather there existe at least one vertex, which is FT! - isFTVertex = this->is_FTVertex(vVertex[i], i); + isFTVertex = this->is_onInterfaceVertex(vVertex[i], i); if ( isFTVertex ) break; } @@ -409,7 +370,7 @@ CollectCorners_FlatTop_2d(GridObject* elem) ////////////////////////////////////////////// // case 1: // vertex insideDomain - if ( !this->is_FTVertex(vrtRoot, i) ) + if ( !this->is_onInterfaceVertex(vrtRoot, i) ) { if ( this->is_nearInterfaceVertex(vrtRoot, i) ) UG_THROW("NearInterface BUT !is_FT => neuerdings Fehler!!....\n"); @@ -467,11 +428,11 @@ CollectCorners_FlatTop_2d(GridObject* elem) if ( this->is_nearInterfaceVertex(vrt2, vrtInd2) || this->is_nearInterfaceVertex(vrt1, vrtInd1) ) { bNearInterface = true; continue; } // case2: vert2 = outsideParticle && vrt1 = insideParticle: - else if ( vrtRoot == vrt1 && !this->is_FTVertex(vrt2, vrtInd2) ){ + else if ( vrtRoot == vrt1 && !this->is_onInterfaceVertex(vrt2, vrtInd2) ){ this->get_intersection_point(intersectionPnt, vrt2, vrt1); } // case3: vrt1 = outsideParticle && vrt2 = insideParticle: - else if ( vrtRoot == vrt2 && !this->is_FTVertex(vrt1, vrtInd1) ) + else if ( vrtRoot == vrt2 && !this->is_onInterfaceVertex(vrt1, vrtInd1) ) this->get_intersection_point(intersectionPnt, vrt1, vrt2); else continue; @@ -536,21 +497,21 @@ update_elem(GridObject* elem, const MathVector* vCornerCoords, int in bool do_update_local = false; this->m_vBF.clear(); -// computing flat top modus +// computing the cut element modus this->m_elemModus = compute_element_modus(elem, interfaceOrientation); switch(this->m_elemModus) { - case INSIDE_DOM: if ( dim == 2 ) this->set_flat_top_data(elem, vCornerCoords, ROID_TRIANGLE); - if ( dim == 3 ) this->set_flat_top_data(elem, vCornerCoords, ROID_TETRAHEDRON); + case INSIDE_DOM: if ( dim == 2 ) this->set_element_data(elem, vCornerCoords, ROID_TRIANGLE); + if ( dim == 3 ) this->set_element_data(elem, vCornerCoords, ROID_TETRAHEDRON); break; // usual assembling - case OUTSIDE_DOM: if ( dim == 2 ) this->set_flat_top_data(elem, vCornerCoords, ROID_TRIANGLE); - if ( dim == 3 ) this->set_flat_top_data(elem, vCornerCoords, ROID_TETRAHEDRON); + case OUTSIDE_DOM: if ( dim == 2 ) this->set_element_data(elem, vCornerCoords, ROID_TRIANGLE); + if ( dim == 3 ) this->set_element_data(elem, vCornerCoords, ROID_TETRAHEDRON); break; // usual assembling - case CUT_BY_INTERFACE: this->compute_flat_top_data(elem); + case CUT_BY_INTERFACE: this->compute_cut_element_data(elem); //if ( m_roid == ROID_PYRAMID )UG_THROW("PYRAMID\n"); do_update_local = true; - break; // flat top assembling + break; // cut element assembling default: throw(UGError("Error in InterfaceHandlerLocalDiffusion::update(): switch(m_elemModus)!")); } diff --git a/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf.h b/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf.h index 4f8dc0d..ef2048d 100644 --- a/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf.h +++ b/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf.h @@ -37,7 +37,7 @@ class InterfaceMapper2PF : public IInterfaceMapper InterfaceMapper2PF(SmartPtr > localHandler) : m_spInterfaceHandlerLocal(localHandler), - m_numDoFs(0), + m_numGridNodes(0), m_resized(false), m_resized_defect(false), m_scaleDoFs(false) @@ -95,12 +95,12 @@ class InterfaceMapper2PF : public IInterfaceMapper LocalVector& get_local_defect_quad() { return m_spInterfaceHandlerLocal->get_local_defect_quad(); } - void write_solution(const std::vector verticesValues) - { m_spInterfaceHandlerLocal->write_solution(verticesValues); } + void set_interface_values(const std::vector verticesValues) + { m_spInterfaceHandlerLocal->set_interface_values(verticesValues); } // called during init() of diffusionInterface: void set_numDoFs(const size_t numDoFs) - { m_numDoFs = numDoFs;} + { m_numGridNodes = numDoFs;} void set_numNewDoFs(const size_t numNewDoFs) { m_numNewDoFs = numNewDoFs;} @@ -109,7 +109,7 @@ class InterfaceMapper2PF : public IInterfaceMapper private: SmartPtr > m_spInterfaceHandlerLocal; // number of DoFs in global matrix - size_t m_numDoFs; + size_t m_numGridNodes; size_t m_numNewDoFs; bool m_resized; bool m_resized_defect; diff --git a/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf_impl.h b/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf_impl.h index d3d4050..5561217 100644 --- a/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf_impl.h +++ b/incompressible/fv1/two_phase_flow/loc_to_glob_mapper_2pf_impl.h @@ -36,12 +36,12 @@ modify_GlobalSol(vector_type& vecMod, const vector_type& vec, ConstSmartPtr siehe MovingInterface2PF.init() for (size_t i = 0; i < numNewDoFs; ++i) { - index = DoFIndex(m_numDoFs + i, 0); + index = DoFIndex(m_numGridNodes + i, 0); double value = DoFRef(vec, index); verticesValue.push_back(value); @@ -71,7 +71,7 @@ modify_GlobalSol(vector_type& vecMod, const vector_type& vec, ConstSmartPtrget_jac_bool(); - if ( !bJac ) - { - // vec.set(0.0); - m_spInterfaceHandlerLocal->set_jac_bool(true); - } -*/ + if ( print ) { - UG_LOG("*** m_numDoFs: " << m_numDoFs << "\n"); + UG_LOG("*** m_numGridNodes: " << m_numGridNodes << "\n"); UG_LOG("*** m_numNewDoFs: " << m_numNewDoFs << "\n"); UG_LOG("*** numAllDoFs: " << numAllDoFs << "\n"); UG_LOG("*** nachher: vec.size(): " << vec.size() << "\n"); @@ -220,10 +213,10 @@ add_local_mat_to_global_interface(matrix_type& mat, const LocalMatrix& lmat, Con const LocalMatrix& locJ_tri = get_local_jacobian_tri(); const bool shift_global_index_tri = m_spInterfaceHandlerLocal->get_index_shift_tri(); - size_t numAllDoFs = m_numDoFs; + size_t numAllDoFs = m_numGridNodes; if ( shift_global_index_tri ) - numAllDoFs = m_numDoFs + m_numNewDoFs; + numAllDoFs = m_numGridNodes + m_numNewDoFs; // UG_LOG("in InterfaceMapper2PF::add_loc_mat(): locJ_tri = " << locJ_tri << "\n"); @@ -266,10 +259,10 @@ add_local_mat_to_global_interface(matrix_type& mat, const LocalMatrix& lmat, Con const bool shift_global_index_quad = m_spInterfaceHandlerLocal->get_index_shift_quad(); // reset numAllDoFs! - numAllDoFs = m_numDoFs; + numAllDoFs = m_numGridNodes; if ( shift_global_index_quad ) - numAllDoFs = m_numDoFs + m_numNewDoFs; + numAllDoFs = m_numGridNodes + m_numNewDoFs; // UG_LOG("in InterfaceMapper2PF::add_loc_mat(): locJ_quad = " << locJ_quad << "\n"); @@ -324,10 +317,10 @@ add_local_vec_to_global_interface(vector_type& vec, const LocalVector& lvec, Con const LocalVector& locD_tri = get_local_defect_tri(); const bool shift_global_index_tri = m_spInterfaceHandlerLocal->get_index_shift_tri(); - size_t numAllDoFs = m_numDoFs; + size_t numAllDoFs = m_numGridNodes; if ( shift_global_index_tri ) - { numAllDoFs = m_numDoFs + m_numNewDoFs; + { numAllDoFs = m_numGridNodes + m_numNewDoFs; UG_LOG("it is shifted!\n"); } // UG_LOG("in InterfaceMapper2PF::add_loc_vec(): locD_tri = " << locD_tri << "\n"); @@ -356,10 +349,10 @@ add_local_vec_to_global_interface(vector_type& vec, const LocalVector& lvec, Con const bool shift_global_index_quad = m_spInterfaceHandlerLocal->get_index_shift_quad(); // reset numAllDoFs! - numAllDoFs = m_numDoFs; + numAllDoFs = m_numGridNodes; if ( shift_global_index_quad ) - numAllDoFs = m_numDoFs + m_numNewDoFs; + numAllDoFs = m_numGridNodes + m_numNewDoFs; // UG_LOG("in InterfaceMapper2PF::add_loc_vec(): locD_quad = " << locD_quad << "\n"); diff --git a/incompressible/fv1/two_phase_flow/two_phase_flow.h b/incompressible/fv1/two_phase_flow/two_phase_flow.h index 7c7b884..c2d232b 100644 --- a/incompressible/fv1/two_phase_flow/two_phase_flow.h +++ b/incompressible/fv1/two_phase_flow/two_phase_flow.h @@ -26,7 +26,7 @@ namespace NavierStokes{ template < typename TDomain, typename TAlgebra> class MovingInterface2PF - : public IMovingInterface + : public IImmersedInterface { public: /// world Dimension @@ -47,7 +47,7 @@ class MovingInterface2PF SmartPtr > ass, SmartPtr > spMaster, SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler, + SmartPtr > cutElementHandler, number fluidDensity1, number fluidDensity2); void set_StdFV_assembling(bool bValue) { m_spInterfaceHandlerLocal->set_StdFV_assembling(bValue);} @@ -106,24 +106,14 @@ class MovingInterface2PF } - void set_interface_values(vector_type& u, const int numDoFs, const int num_newDoFs) - { -// double value = 20.0*0.4*0.4*0.4*0.4; - DoFIndex index; - - for (size_t i = 0; i < num_newDoFs; ++i) - { - index = DoFIndex(numDoFs + i,0); - // DoFRef(u, index) = value; - } - } + void set_analytic_solution(vector_type& u, SmartPtr > spApproxSpace, SmartPtr mg, const int topLevel); void adjust_for_error(vector_type& u, vector_type& uCopy, SmartPtr > spApproxSpace, SmartPtr mg, const int topLevel); double compute_solution_value(const MathVector& vrtPos); - number get_integral() - { return m_spInterfaceHandlerLocal->get_integral(); } + number get_L2Error() + { return m_spInterfaceHandlerLocal->get_L2Error(); } void init(vector_type& u, SmartPtr > spApproxSpace, const int baseLevel, const int topLevel, bool bScaleDoFs) { @@ -154,12 +144,9 @@ class MovingInterface2PF m_spInterfaceMapper->set_bScaleDoFs(bScaleDoFs); m_spInterfaceHandlerLocal->set_bScaleDoFs(bScaleDoFs); - m_spInterfaceHandlerLocal->init_integral(); - - // lieber in jedem Schritt ueber 'modify_GlobalSol()' (mapper!) setzten! - //set_interface_values(u, numDoFs, num_newDoFs); + m_spInterfaceHandlerLocal->L2Error_init(); - // not necessary anymore: only local evaluations within diffusion problem! + // not necessary anymore: only local evaluations within diffusion problem! //m_spCutElementHandler->template init_marker(dd, baseLevel, topLevel); } @@ -178,25 +165,22 @@ class MovingInterface2PF bool is_time_dependent() { return m_spInterfaceHandlerLocal->is_time_dependent();} - /// helper functions for compute_error_on_circle() - void interpolate_point(ConstSmartPtr dd, const vector_type& u, + void interpolate_point(ConstSmartPtr dd, const vector_type& u, const MathVector& evalPos, MathVector& interpolation); - void compute_error_on_circle(const vector_type& u, const int topLevel, number radius); - + void print_deltaP(const vector_type& u, const int topLevel); void print_pressure(const vector_type& u, const int topLevel); void print_pressure_nodal(const vector_type& u, const int topLevel); /// writing data to file; called via .lua void print_velocity(const vector_type& u, const int topLevel, number time, const char* filename); - void print_velocity_many_particles(const vector_type& u, const int topLevel, number time, const char* filename); - + private: /// current ApproxSpace SmartPtr > m_spApproxSpace; SmartPtr > m_spInterfaceProvider; - SmartPtr > m_spCutElementHandler; + SmartPtr > m_spCutElementHandler; SmartPtr > m_spInterfaceHandlerLocal; SmartPtr > m_spInterfaceMapper; diff --git a/incompressible/fv1/two_phase_flow/two_phase_flow_impl.h b/incompressible/fv1/two_phase_flow/two_phase_flow_impl.h index abe7887..2a9d4d7 100644 --- a/incompressible/fv1/two_phase_flow/two_phase_flow_impl.h +++ b/incompressible/fv1/two_phase_flow/two_phase_flow_impl.h @@ -1,6 +1,6 @@ /* - * moving_interface_diffusion_impl.h + * two_phase_flow_impl.h * * Created on: 24.08.2017 * Author: suze @@ -23,7 +23,7 @@ template MovingInterface2PF::MovingInterface2PF( SmartPtr > ass, SmartPtr > spMaster, SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler, + SmartPtr > cutElementHandler, number fluidDensity1, number fluidDensity2) : m_spInterfaceProvider(interfaceProvider), m_spInterfaceHandlerLocal(new InterfaceHandlerLocal2PF(interfaceProvider, cutElementHandler, fluidDensity1, fluidDensity2)), @@ -81,8 +81,7 @@ set_analytic_solution(vector_type& u, SmartPtr > spA typedef Attachment position_attachment_type; typedef Grid::VertexAttachmentAccessor position_accessor_type; - //SmartPtr m_spMG = mg.operator->(); - position_attachment_type m_aPos = GetDefaultPositionAttachment(); + position_attachment_type m_aPos = GetDefaultPositionAttachment(); position_accessor_type m_aaPos; if(!mg->has_attachment(m_aPos)) @@ -142,8 +141,7 @@ adjust_for_error(vector_type& u, vector_type& uCopy, SmartPtr position_attachment_type; typedef Grid::VertexAttachmentAccessor position_accessor_type; - //SmartPtr m_spMG = mg.operator->(); - position_attachment_type m_aPos = GetDefaultPositionAttachment(); + position_attachment_type m_aPos = GetDefaultPositionAttachment(); position_accessor_type m_aaPos; if(!mg->has_attachment(m_aPos)) @@ -162,7 +160,7 @@ adjust_for_error(vector_type& u, vector_type& uCopy, SmartPtrcompute_element_modus(elem, 1); + ElementModus elemModus = m_spInterfaceHandlerLocal->compute_element_modus(elem); bool do_adjust = false; switch(elemModus) @@ -213,7 +211,7 @@ initialize_interface(vector_type& u, ConstSmartPtr dd) // get element grid_base_object* elem = *iter; - ElementModus elemModus = m_spCutElementHandler->compute_element_modus(elem, 1); + ElementModus elemModus = m_spCutElementHandler->compute_element_modus(elem); if ( elemModus == CUT_BY_INTERFACE ) num_cutElements += 1; @@ -294,29 +292,22 @@ update_interface( const int topLevel, number deltaT) // get level index const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - UG_LOG("update_prtCoords() for levIndex = " << levIndex << "\n"); - UG_LOG("update_prtCoords() for deltaT = " << deltaT << "\n"); - + // update center for (size_t p = 0; p < m_spInterfaceProvider->num_particles(); ++p) { #ifdef UG_PARALLEL std::vector ElemList = m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; std::vector ElemList = m_vvvElemListCut[levIndex][p]; - UG_LOG("1_ update_prtCoords() ElemList.size(): " << ElemList.size() << "\n"); - if ( ElemList.size() == 0 ) { - UG_LOG("2_ update_prtCoords() ElemList.size(): " << ElemList.size() << " => skip assembling! \n"); - continue; - } + if ( ElemList.size() == 0 ) + { continue; } #endif // get data: MathVector centerNew = m_spInterfaceProvider->get_center(p); number soution = m_spInterfaceProvider->get_solution(p, 0); - UG_LOG(" solution = " << soution << "\n"); - UG_LOG("deltaT = " << deltaT << "\n"); - -// ToDo: Hier das interface irgendwie updaten?? + + // ToDo: Hier das interface updaten: } // end particle loop diff --git a/incompressible/particle_laden_flow_plugin Kopie.cpp b/incompressible/particle_laden_flow_plugin Kopie.cpp deleted file mode 100644 index 963c229..0000000 --- a/incompressible/particle_laden_flow_plugin Kopie.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt - * Author: Sebastian Reiter - * - * This file is part of UG4. - * - * UG4 is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License version 3 (as published by the - * Free Software Foundation) with the following additional attribution - * requirements (according to LGPL/GPL v3 §7): - * - * (1) The following notice must be displayed in the Appropriate Legal Notices - * of covered and combined works: "Based on UG4 (www.ug4.org/license)". - * - * (2) The following notice must be displayed at a prominent place in the - * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". - * - * (3) The following bibliography is recommended for citation and must be - * preserved in all covered files: - * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively - * parallel geometric multigrid solver on hierarchically distributed grids. - * Computing and visualization in science 16, 4 (2013), 151-164" - * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel - * flexible software system for simulating pde based models on high performance - * computers. Computing and visualization in science 16, 4 (2013), 165-179" - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - */ - -#ifdef UG_PARALLEL - #include "../../Parmetis/src/unificator_interface.h" -#endif - -#include "bridge/util.h" -#include "bridge/util_domain_algebra_dependent.h" - -#include "common/log.h" -#include "lib_disc/function_spaces/grid_function.h" -#include "lib_disc/dof_manager/dof_distribution.h" -#include "fv1/navier_stokes_fv1.h" -#include "incompressible_navier_stokes_base.h" -#include "fv1/bnd/inflow_fv1.h" -#include "bnd/inflow_base.h" - - -#include "lib_disc/spatial_disc/local_to_global/local_to_global_mapper.h" -#include "fv1/immersed_interface_base/gmg_transfer/particle_transfer.h" -#include "fv1/moving_particle/interface_handler_particle.h" -#include "fv1/moving_particle/moving_particle.h" -#include "fv1/diffusion_interface/interface_handler_diffusion.h" -#include "fv1/diffusion_interface/diffusion_interface.h" -//#include "fv1/two_phase_flow/two_phase_flow.h" - - -using namespace std; -using namespace ug::bridge; - -namespace ug{ -namespace ParticleLadenFlow{ - -/** - * Class exporting the functionality of the plugin. All functionality that is to - * be used in scripts or visualization must be registered here. - */ -struct FunctionalityIncomp -{ - -/** - * Function called for the registration of Domain and Algebra dependent parts - * of the plugin. All Functions and Classes depending on both Domain and Algebra - * are to be placed here when registering. The method is called for all - * available Domain and Algebra types, based on the current build options. - * - * @param reg registry - * @param parentGroup group for sorting of functionality - */ -template -static void DomainAlgebra(Registry& reg, string grp) -{ - string suffix = GetDomainAlgebraSuffix(); - string tag = GetDomainAlgebraTag(); - - typedef ApproximationSpace approximation_space_type; - typedef GridFunction function_type; - -// IMovingInterfaceBase - { - typedef MovingInterfaceBase::IMovingInterface T; - string name = string("IMovingInterfaceBase").append(suffix); - reg.add_class_(name, grp); - reg.add_class_to_group(name, "IMovingInterfaceBase", tag); - - } -/* - // MovingInterface2PF - { - typedef MovingInterface2PF::MovingInterface2PF T; - typedef MovingInterfaceBase::IMovingInterface TBase; - string name = string("MovingInterface2PF").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > ass, - SmartPtr > spMaster, SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler, - number fluidDensity1, number fluidDensity2)>("domain disc, global handler") - .add_method("init", &T::init) - .add_method("get_integral", &T::get_integral) - .add_method("adjust_for_error", &T::adjust_for_error) - .add_method("initialize_threshold", &T::initialize_threshold) - .add_method("set_threshold", &T::set_threshold, "", "Set Threshold") - .add_method("set_analytic_solution", &T::set_analytic_solution, "", "Set Threshold") - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "MovingInterface2PF", tag); - } - - // MovingInterfaceDiffusionFE - { - typedef MovingInterfaceDiffusionFE::MovingInterfaceDiffusionFE T; - typedef MovingInterfaceBase::IMovingInterface TBase; - string name = string("MovingInterfaceDiffusionFE").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > ass, - SmartPtr > spMaster, - SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler)>("domain disc, global handler") - .add_method("init", &T::init) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "MovingInterfaceDiffusionFE", tag); - } - */ - // MovingInterfaceDiffusion - { - - typedef MovingInterfaceDiffusion::MovingInterfaceDiffusion T; - typedef MovingInterfaceBase::IMovingInterface TBase; - string name = string("MovingInterfaceDiffusion").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > ass, - SmartPtr > spMaster, - SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler)>("domain disc, global handler") - .add_method("init", &T::init) - .add_method("get_integral", &T::get_integral) - .add_method("get_numDoFs", &T::get_numDoFs) - .add_method("set_Nitsche", &T::set_Nitsche) - .add_method("adjust_for_error", &T::adjust_for_error) - .add_method("initialize_threshold", &T::initialize_threshold) - .add_method("set_threshold", &T::set_threshold, "", "Set Threshold") - .add_method("set_analytic_solution", &T::set_analytic_solution, "", "Set Threshold") - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "MovingInterfaceDiffusion", tag); - } - -// MovingParticle - { - typedef MovingParticle::MovingParticle T; - typedef MovingInterfaceBase::IMovingInterface TBase; - string name = string("MovingParticle").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > ass, - SmartPtr > spMaster, - SmartPtr > cutElementHandler, - number fluidDensity, number fluidKinVisc)>("domain disc, global handler") - .add_method("init", &T::init) - // .add_method("compute_functional_combined", &T::compute_functional_combined) - .add_method("compute_functional", &T::compute_functional) - .add_method("compute_functional_all", &T::compute_functional_all) - .add_method("gradient_descent", &T::gradient_descent) - .add_method("project_directions", &T::project_directions) - .add_method("rescale_directions", &T::rescale_directions) - .add_method("print_velocity", &T::print_velocity) - // .add_method("print_velocity_many_particles", &T::print_velocity_many_particles) - .add_method("print_pressure", &T::print_pressure) - .add_method("print_deltaP", &T::print_deltaP) - .add_method("print_pressure_nodal", &T::print_pressure_nodal) - // .add_method("compute_error_on_circle", &T::compute_error_on_circle) - .add_method("update", &T::update) - .add_method("get_velocity", &T::get_velocity) - .add_method("adjust_global_solution", &T::adjust_global_solution) - .add_method("compute_gradient_local_max", &T::compute_gradient_local_max) - .add_method("set_gravity", &T::set_gravity) - .add_method("set_time_step", &T::set_time_step) - .add_method("set_volume_comp_mode", &T::set_volume_comp_mode) - .add_method("set_StdFV_assembling", &T::set_StdFV_assembling) - .add_method("initialize_threshold", &T::initialize_threshold) - .add_method("get_BndCond", &T::get_BndCond) -// .add_method("get_particles", &T::get_particles) - // methods for parallel many-particle simulations: -#ifdef UG_PARALLEL - .add_method("pre_balancing_update", &T::pre_balancing_update) - .add_method("post_balancing_update", &T::post_balancing_update) -#endif - .add_method("set_repulsive_force", &T::set_repulsive_force) - .add_method("set_glowinski_repulsive_force", &T::set_glowinski_repulsive_force) - .add_method("set_minimum_correction_force", &T::set_minimum_correction_force) - .add_method("set_element_diameter", &T::set_element_diameter) - .add_method("MeanElementDiameter", &T::MeanElementDiameter) - .add_method("set_forceLog", &T::set_forceLog) - .add_method("set_mpi_routine", &T::set_mpi_routine) - .add_method("estimate_repulsive_force_parameters", &T::estimate_repulsive_force_parameters) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "MovingParticle", tag); - } - - // ParticleTransfer - { - typedef ParticleTransfer T; - typedef ITransferOperator TBase; - string name = string("ParticleTransfer").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > approxSpace, SmartPtr > cutElementHandler)>("approxSpace, globalHandler") - .add_method("set_debug", &T::set_debug, "", "") - .add_method("set_use_transposed", &T::set_use_transposed, "", "") - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "ParticleTransfer", tag); - } - -} - -/** - * Function called for the registration of Algebra dependent parts. - * All Functions and Classes depending on Algebra - * are to be placed here when registering. The method is called for all - * available Algebra types, based on the current build options. - * - * @param reg registry - * @param parentGroup group for sorting of functionality - */ -template -static void Algebra(Registry& reg, string grp) -{ - string suffix = GetAlgebraSuffix(); - string tag = GetAlgebraTag(); -} - -/** - * Function called for the registration of Domain dependent parts - * of the plugin. All Functions and Classes depending on the Domain - * are to be placed here when registering. The method is called for all - * available Domain types, based on the current build options. - * - * @param reg registry - * @param parentGroup group for sorting of functionality - */ -template -static void Domain(Registry& reg, string grp) -{ - string suffix = GetDomainSuffix(); - string tag = GetDomainTag(); - - // ParticleBndCond - { - typedef MovingParticle::ParticleBndCond T; - typedef IElemDisc TBase; - string name = string("ParticleBndCond").append(suffix); - reg.add_class_(name, grp), - reg.add_class_to_group(name, "ParticleBndCond", tag); - } -#ifdef UG_PARALLEL - // ParticleUnificator - { - typedef MovingParticle::ParticleUnificator T; - typedef typename GeomObjBaseTypeByDim::base_obj_type TBaseElem; - typedef parmetis::IUnificator TBase; - string name = string("ParticleUnificator").append(suffix); - reg.add_class_(name, grp) - .template add_constructor)>("") - .add_method("update_particles", &T::update_particles) - .add_method("rebalance", &T::rebalance) - .set_construct_as_smart_pointer(true); - // .add_method("get_weight", &T::get_weight); - // .add_method("reweight", &T::reweight); - reg.add_class_to_group(name, "ParticleUnificator", tag); - } -#endif - -} - -/** - * Function called for the registration of Dimension dependent parts - * of the plugin. All Functions and Classes depending on the Dimension - * are to be placed here when registering. The method is called for all - * available Dimension types, based on the current build options. - * - * @param reg registry - * @param parentGroup group for sorting of functionality - */ -template -static void Dimension(Registry& reg, string grp) -{ - string suffix = GetDimensionSuffix(); - string tag = GetDimensionTag(); - - // CutElementHandlerFlatTop - { - typedef MovingInterfaceBase::CutElementHandlerFlatTop T; - string name = string("CutElementHandlerFlatTop").append(suffix); - reg.add_class_(name, grp) - .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") - .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") - // .add_method("update_prtCoords", &T::update_prtCoords) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "CutElementHandlerFlatTop", tag); - } - - // CutElementHandlerImmersed - { - typedef MovingInterfaceBase::CutElementHandlerImmersed T; - string name = string("CutElementHandlerImmersed").append(suffix); - reg.add_class_(name, grp) - .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "CutElementHandlerImmersed", tag); - } - - // ParticleProvider - { - typedef MovingParticle::ParticleProvider T; - string name = string("ParticleProvider").append(suffix); - reg.add_class_(name, grp) - .template add_constructor("") - .add_method("print", &T::print) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "ParticleProvider", tag); - } - - - // ParticleProviderSphere - { - typedef MovingParticle::ParticleProviderSphere T; - string name = string("ParticleProviderSphere").append(suffix); - reg.add_class_(name, grp) - .template add_constructor("") - .add_method("print", &T::print) - .add_method("add", &T::add) - .add_method("add_moving", &T::add_moving) -// .add_method("get_collision_time", &T::get_collision_time) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "ParticleProviderSphere", tag); - } - - // ParticleProviderEllipse - { - typedef MovingParticle::ParticleProviderEllipse T; - string name = string("ParticleProviderEllipse").append(suffix); - reg.add_class_(name, grp) - .template add_constructor("") - .add_method("print", &T::print) - .add_method("add", &T::add) - .add_method("add_moving", &T::add_moving) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "ParticleProviderEllipse", tag); - } - - // DiffusionInterfaceProvider - { - typedef MovingInterfaceBase::DiffusionInterfaceProvider T; - string name = string("DiffusionInterfaceProvider").append(suffix); - reg.add_class_(name, grp) - .template add_constructor("") - .add_method("print", &T::print) - .add_method("add", &T::add) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "DiffusionInterfaceProvider", tag); - } - - -} - - -static void Common(Registry& reg, string grp) -{ - // write numbers into file - /* TODO: obsolete / replace by lua code */ - { - //reg.add_function("writeNumbers", static_cast(&writeNumbers), grp); - } - // write numbers into file - /* TODO: obsolete / replace by lua code */ - { - //reg.add_function("clearFile", static_cast(&clearFile), grp); - } -} - -}; // end Functionality -} // end namespace ParticleLadenFlow - - -/** - * This function is called when the plugin is loaded. - */ -void Init___ParticleLadenFlow(Registry* reg, string grp) -{ - grp.append("SpatialDisc/NavierStokes/"); - typedef ParticleLadenFlow::FunctionalityIncomp Functionality; - - try{ - RegisterDimension2d3dDependent(*reg,grp); - RegisterDomain2d3dDependent(*reg,grp); - RegisterDomain2d3dAlgebraDependent(*reg,grp); - -// RegisterAlgebraDependent(*reg,grp); - - } - UG_REGISTRY_CATCH_THROW(grp); -} - - - -}// namespace ug - - diff --git a/incompressible/particle_laden_flow_plugin.cpp b/incompressible/particle_laden_flow_plugin.cpp index 19b3972..2c78dcc 100644 --- a/incompressible/particle_laden_flow_plugin.cpp +++ b/incompressible/particle_laden_flow_plugin.cpp @@ -30,6 +30,9 @@ * GNU Lesser General Public License for more details. */ +#ifndef MOVING_PARTICLE_PLUGIN_CPP_ +#define MOVING_PARTICLE_PLUGIN_CPP_ + #ifdef UG_PARALLEL #include "../../Parmetis/src/unificator_interface.h" #endif @@ -40,9 +43,9 @@ #include "common/log.h" #include "lib_disc/function_spaces/grid_function.h" #include "lib_disc/dof_manager/dof_distribution.h" -#include "fv1/navier_stokes_fv1.h" +#include "fv1/navier_stokes_fv1_cutElem.h" #include "incompressible_navier_stokes_base.h" -#include "fv1/bnd/inflow_fv1.h" +#include "fv1/bnd/inflow_fv1_cutElem.h" #include "bnd/inflow_base.h" @@ -83,75 +86,32 @@ static void DomainAlgebra(Registry& reg, string grp) typedef ApproximationSpace approximation_space_type; typedef GridFunction function_type; -// IMovingInterfaceBase +// IImmersedInterfaceBase { - typedef IMovingInterface T; - string name = string("IMovingInterfaceBase").append(suffix); + typedef IImmersedInterface T; + string name = string("IImmersedInterface").append(suffix); reg.add_class_(name, grp); - reg.add_class_to_group(name, "IMovingInterfaceBase", tag); + reg.add_class_to_group(name, "IImmersedInterface", tag); } -/* - // MovingInterface2PF - { - typedef MovingInterface2PF::MovingInterface2PF T; - typedef IMovingInterface TBase; - string name = string("MovingInterface2PF").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > ass, - SmartPtr > spMaster, SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler, - number fluidDensity1, number fluidDensity2)>("domain disc, global handler") - .add_method("init", &T::init) - .add_method("get_integral", &T::get_integral) - .add_method("adjust_for_error", &T::adjust_for_error) - .add_method("initialize_threshold", &T::initialize_threshold) - .add_method("set_threshold", &T::set_threshold, "", "Set Threshold") - .add_method("set_analytic_solution", &T::set_analytic_solution, "", "Set Threshold") - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "MovingInterface2PF", tag); - } - - // MovingInterfaceDiffusionFE - { - typedef MovingInterfaceDiffusionFE::MovingInterfaceDiffusionFE T; - typedef IMovingInterface TBase; - string name = string("MovingInterfaceDiffusionFE").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > ass, - SmartPtr > spMaster, - SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler)>("domain disc, global handler") - .add_method("init", &T::init) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "MovingInterfaceDiffusionFE", tag); - } - */ + // MovingParticle { typedef MovingParticle T; - typedef IMovingInterface TBase; + typedef IImmersedInterface TBase; string name = string("MovingParticle").append(suffix); reg.add_class_(name, grp) .template add_constructor > ass, - SmartPtr > spMaster, - SmartPtr > cutElementHandler, + SmartPtr > spMaster, + SmartPtr > cutElementHandler, number fluidDensity, number fluidKinVisc)>("domain disc, global handler") .add_method("init", &T::init) - // .add_method("compute_functional_combined", &T::compute_functional_combined) - .add_method("compute_functional", &T::compute_functional) - .add_method("compute_functional_all", &T::compute_functional_all) - .add_method("gradient_descent", &T::gradient_descent) - .add_method("project_directions", &T::project_directions) - .add_method("rescale_directions", &T::rescale_directions) .add_method("print_velocity", &T::print_velocity) - // .add_method("print_velocity_many_particles", &T::print_velocity_many_particles) - .add_method("print_pressure", &T::print_pressure) .add_method("print_deltaP", &T::print_deltaP) .add_method("print_pressure_nodal", &T::print_pressure_nodal) - // .add_method("compute_error_on_circle", &T::compute_error_on_circle) + .add_method("print_pressure_teta", &T::print_pressure_teta) .add_method("update", &T::update) .add_method("get_velocity", &T::get_velocity) .add_method("adjust_global_solution", &T::adjust_global_solution) @@ -160,9 +120,11 @@ static void DomainAlgebra(Registry& reg, string grp) .add_method("set_time_step", &T::set_time_step) .add_method("set_volume_comp_mode", &T::set_volume_comp_mode) .add_method("set_StdFV_assembling", &T::set_StdFV_assembling) + .add_method("set_print_cutElemData", &T::set_print_cutElemData) .add_method("initialize_threshold", &T::initialize_threshold) + .add_method("set_threshold", &T::set_threshold) .add_method("get_BndCond", &T::get_BndCond) -// .add_method("get_particles", &T::get_particles) + .add_method("get_numCutElements", &T::get_numCutElements) // methods for parallel many-particle simulations: #ifdef UG_PARALLEL .add_method("pre_balancing_update", &T::pre_balancing_update) @@ -186,7 +148,7 @@ static void DomainAlgebra(Registry& reg, string grp) typedef ITransferOperator TBase; string name = string("ParticleTransfer").append(suffix); reg.add_class_(name, grp) - .template add_constructor > approxSpace, SmartPtr > cutElementHandler)>("approxSpace, globalHandler") + .template add_constructor > approxSpace, SmartPtr > cutElementHandler)>("approxSpace, globalHandler") .add_method("set_debug", &T::set_debug, "", "") .add_method("set_use_transposed", &T::set_use_transposed, "", "") .set_construct_as_smart_pointer(true); @@ -269,16 +231,16 @@ static void Dimension(Registry& reg, string grp) string suffix = GetDimensionSuffix(); string tag = GetDimensionTag(); - // CutElementHandlerFlatTop + // CutElementHandler_FlatTop { - typedef CutElementHandlerFlatTop T; - string name = string("CutElementHandlerFlatTop").append(suffix); + typedef CutElementHandler_FlatTop T; + string name = string("CutElementHandler_FlatTop").append(suffix); reg.add_class_(name, grp) .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") // .add_method("update_prtCoords", &T::update_prtCoords) .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "CutElementHandlerFlatTop", tag); + reg.add_class_to_group(name, "CutElementHandler_FlatTop", tag); } @@ -364,3 +326,4 @@ void Init___ParticleLadenFlow(Registry* reg, string grp) }// namespace ug +#endif /* MOVING_PARTICLE_PLUGIN_CPP_ */ diff --git a/incompressible/particle_laden_flow_plugin_origJonas.cpp b/incompressible/particle_laden_flow_plugin_origJonas.cpp deleted file mode 100644 index 8c6feca..0000000 --- a/incompressible/particle_laden_flow_plugin_origJonas.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt - * Author: Sebastian Reiter - * - * This file is part of UG4. - * - * UG4 is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License version 3 (as published by the - * Free Software Foundation) with the following additional attribution - * requirements (according to LGPL/GPL v3 §7): - * - * (1) The following notice must be displayed in the Appropriate Legal Notices - * of covered and combined works: "Based on UG4 (www.ug4.org/license)". - * - * (2) The following notice must be displayed at a prominent place in the - * terminal output of covered works: "Based on UG4 (www.ug4.org/license)". - * - * (3) The following bibliography is recommended for citation and must be - * preserved in all covered files: - * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively - * parallel geometric multigrid solver on hierarchically distributed grids. - * Computing and visualization in science 16, 4 (2013), 151-164" - * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel - * flexible software system for simulating pde based models on high performance - * computers. Computing and visualization in science 16, 4 (2013), 165-179" - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - */ - -#ifdef UG_PARALLEL - #include "../../Parmetis/src/unificator_interface.h" -#endif - -#include "bridge/util.h" -#include "bridge/util_domain_algebra_dependent.h" - -#include "common/log.h" -#include "lib_disc/function_spaces/grid_function.h" -#include "lib_disc/dof_manager/dof_distribution.h" -#include "fv1/navier_stokes_fv1.h" -#include "incompressible_navier_stokes_base.h" -#include "fv1/bnd/inflow_fv1.h" -#include "bnd/inflow_base.h" - - -#include "lib_disc/spatial_disc/local_to_global/local_to_global_mapper.h" -#include "fv1/immersed_interface_base/gmg_transfer/particle_transfer.h" -#include "fv1/moving_particle/interface_handler_particle.h" -#include "fv1/moving_particle/moving_particle.h" -//#include "fv1/diffusion_interface/interface_handler_diffusion.h" -//#include "fv1/diffusion_interface/diffusion_interface.h" -//#include "fv1/two_phase_flow/two_phase_flow.h" - - -using namespace std; -using namespace ug::bridge; - -namespace ug{ -namespace ParticleLadenFlow{ - -/** - * Class exporting the functionality of the plugin. All functionality that is to - * be used in scripts or visualization must be registered here. - */ -struct FunctionalityIncomp -{ - -/** - * Function called for the registration of Domain and Algebra dependent parts - * of the plugin. All Functions and Classes depending on both Domain and Algebra - * are to be placed here when registering. The method is called for all - * available Domain and Algebra types, based on the current build options. - * - * @param reg registry - * @param parentGroup group for sorting of functionality - */ -template -static void DomainAlgebra(Registry& reg, string grp) -{ - string suffix = GetDomainAlgebraSuffix(); - string tag = GetDomainAlgebraTag(); - - typedef ApproximationSpace approximation_space_type; - typedef GridFunction function_type; - -// IMovingInterfaceBase - { - typedef MovingInterfaceBase::IMovingInterface T; - string name = string("IMovingInterfaceBase").append(suffix); - reg.add_class_(name, grp); - reg.add_class_to_group(name, "IMovingInterfaceBase", tag); - - } -/* - // MovingInterface2PF - { - typedef MovingInterface2PF::MovingInterface2PF T; - typedef MovingInterfaceBase::IMovingInterface TBase; - string name = string("MovingInterface2PF").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > ass, - SmartPtr > spMaster, SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler, - number fluidDensity1, number fluidDensity2)>("domain disc, global handler") - .add_method("init", &T::init) - .add_method("get_integral", &T::get_integral) - .add_method("adjust_for_error", &T::adjust_for_error) - .add_method("initialize_threshold", &T::initialize_threshold) - .add_method("set_threshold", &T::set_threshold, "", "Set Threshold") - .add_method("set_analytic_solution", &T::set_analytic_solution, "", "Set Threshold") - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "MovingInterface2PF", tag); - } - - // MovingInterfaceDiffusionFE - { - typedef MovingInterfaceDiffusionFE::MovingInterfaceDiffusionFE T; - typedef MovingInterfaceBase::IMovingInterface TBase; - string name = string("MovingInterfaceDiffusionFE").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > ass, - SmartPtr > spMaster, - SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler)>("domain disc, global handler") - .add_method("init", &T::init) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "MovingInterfaceDiffusionFE", tag); - } - - // MovingInterfaceDiffusion - { - - typedef MovingInterfaceDiffusion::MovingInterfaceDiffusion T; - typedef MovingInterfaceBase::IMovingInterface TBase; - string name = string("MovingInterfaceDiffusion").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > ass, - SmartPtr > spMaster, - SmartPtr > interfaceProvider, - SmartPtr > cutElementHandler)>("domain disc, global handler") - .add_method("init", &T::init) - .add_method("get_integral", &T::get_integral) - .add_method("set_Nitsche", &T::set_Nitsche) - .add_method("adjust_for_error", &T::adjust_for_error) - .add_method("initialize_threshold", &T::initialize_threshold) - .add_method("set_threshold", &T::set_threshold, "", "Set Threshold") - .add_method("set_analytic_solution", &T::set_analytic_solution, "", "Set Threshold") - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "MovingInterfaceDiffusion", tag); - } - */ -// MovingParticle - { - typedef MovingParticle::MovingParticle T; - typedef MovingInterfaceBase::IMovingInterface TBase; - string name = string("MovingParticle").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > ass, - SmartPtr > spMaster, - SmartPtr > cutElementHandler, - number fluidDensity, number fluidKinVisc)>("domain disc, global handler") - .add_method("init", &T::init) -// .add_method("compute_functional_combined", &T::compute_functional_combined) - .add_method("compute_functional", &T::compute_functional) - .add_method("compute_functional_all", &T::compute_functional_all) - .add_method("gradient_descent", &T::gradient_descent) - .add_method("project_directions", &T::project_directions) - .add_method("rescale_directions", &T::rescale_directions) - .add_method("print_velocity", &T::print_velocity) -// .add_method("print_velocity_many_particles", &T::print_velocity_many_particles) - .add_method("print_pressure", &T::print_pressure) - .add_method("print_deltaP", &T::print_deltaP) - .add_method("print_pressure_nodal", &T::print_pressure_nodal) -// .add_method("compute_error_on_circle", &T::compute_error_on_circle) - .add_method("update", &T::update) - .add_method("get_velocity", &T::get_velocity) - .add_method("adjust_global_solution", &T::adjust_global_solution) - .add_method("compute_gradient_local_max", &T::compute_gradient_local_max) - .add_method("set_gravity", &T::set_gravity) - .add_method("set_time_step", &T::set_time_step) - .add_method("set_volume_comp_mode", &T::set_volume_comp_mode) - .add_method("set_StdFV_assembling", &T::set_StdFV_assembling) - .add_method("initialize_threshold", &T::initialize_threshold) - .add_method("get_BndCond", &T::get_BndCond) -// .add_method("get_particles", &T::get_particles) - // methods for parallel many-particle simulations: -#ifdef UG_PARALLEL - .add_method("pre_balancing_update", &T::pre_balancing_update) - .add_method("post_balancing_update", &T::post_balancing_update) -#endif - .add_method("set_repulsive_force", &T::set_repulsive_force) - .add_method("set_glowinski_repulsive_force", &T::set_glowinski_repulsive_force) - .add_method("set_minimum_correction_force", &T::set_minimum_correction_force) - .add_method("set_element_diameter", &T::set_element_diameter) - .add_method("MeanElementDiameter", &T::MeanElementDiameter) - .add_method("set_forceLog", &T::set_forceLog) - .add_method("set_mpi_routine", &T::set_mpi_routine) - .add_method("estimate_repulsive_force_parameters", &T::estimate_repulsive_force_parameters) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "MovingParticle", tag); - } - - // ParticleTransfer - { - typedef ParticleTransfer T; - typedef ITransferOperator TBase; - string name = string("ParticleTransfer").append(suffix); - reg.add_class_(name, grp) - .template add_constructor > approxSpace, SmartPtr > cutElementHandler)>("approxSpace, globalHandler") - .add_method("set_debug", &T::set_debug, "", "") - .add_method("set_use_transposed", &T::set_use_transposed, "", "") - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "ParticleTransfer", tag); - } - -} - -/** - * Function called for the registration of Algebra dependent parts. - * All Functions and Classes depending on Algebra - * are to be placed here when registering. The method is called for all - * available Algebra types, based on the current build options. - * - * @param reg registry - * @param parentGroup group for sorting of functionality - */ -template -static void Algebra(Registry& reg, string grp) -{ - string suffix = GetAlgebraSuffix(); - string tag = GetAlgebraTag(); -} - -/** - * Function called for the registration of Domain dependent parts - * of the plugin. All Functions and Classes depending on the Domain - * are to be placed here when registering. The method is called for all - * available Domain types, based on the current build options. - * - * @param reg registry - * @param parentGroup group for sorting of functionality - */ -template -static void Domain(Registry& reg, string grp) -{ - string suffix = GetDomainSuffix(); - string tag = GetDomainTag(); - - // ParticleBndCond - { - typedef MovingParticle::ParticleBndCond T; - typedef IElemDisc TBase; - string name = string("ParticleBndCond").append(suffix); - reg.add_class_(name, grp), - reg.add_class_to_group(name, "ParticleBndCond", tag); - } - -#ifdef UG_PARALLEL - // ParticleUnificator - { - typedef MovingParticle::ParticleUnificator T; - typedef typename GeomObjBaseTypeByDim::base_obj_type TBaseElem; - typedef parmetis::IUnificator TBase; - string name = string("ParticleUnificator").append(suffix); - reg.add_class_(name, grp) - .template add_constructor)>("") - .add_method("update_particles", &T::update_particles) - .add_method("rebalance", &T::rebalance) - .set_construct_as_smart_pointer(true); - // .add_method("get_weight", &T::get_weight); - // .add_method("reweight", &T::reweight); - reg.add_class_to_group(name, "ParticleUnificator", tag); - } -#endif - -} - -/** - * Function called for the registration of Dimension dependent parts - * of the plugin. All Functions and Classes depending on the Dimension - * are to be placed here when registering. The method is called for all - * available Dimension types, based on the current build options. - * - * @param reg registry - * @param parentGroup group for sorting of functionality - */ -template -static void Dimension(Registry& reg, string grp) -{ - string suffix = GetDimensionSuffix(); - string tag = GetDimensionTag(); - - // CutElementHandlerFlatTop - { - typedef MovingInterfaceBase::CutElementHandlerFlatTop T; - string name = string("CutElementHandlerFlatTop").append(suffix); - reg.add_class_(name, grp) - .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") - .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") - // .add_method("update_prtCoords", &T::update_prtCoords) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "CutElementHandlerFlatTop", tag); - } - /* - // CutElementHandlerImmersed - { - typedef MovingInterfaceBase::CutElementHandlerImmersed T; - string name = string("CutElementHandlerImmersed").append(suffix); - reg.add_class_(name, grp) - .template add_constructor mg, const char*, SmartPtr >)>("multigrid, fct names") - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "CutElementHandlerImmersed", tag); - } - */ - // ParticleProvider - { - typedef MovingParticle::ParticleProvider T; - string name = string("ParticleProvider").append(suffix); - reg.add_class_(name, grp) - .template add_constructor("") - .add_method("print", &T::print) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "ParticleProvider", tag); - } - - - // ParticleProviderSphere - { - typedef MovingParticle::ParticleProviderSphere T; - string name = string("ParticleProviderSphere").append(suffix); - reg.add_class_(name, grp) - .template add_constructor("") - .add_method("print", &T::print) - .add_method("add", &T::add) - .add_method("add_moving", &T::add_moving) -// .add_method("get_collision_time", &T::get_collision_time) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "ParticleProviderSphere", tag); - } - - // ParticleProviderEllipse - { - typedef MovingParticle::ParticleProviderEllipse T; - string name = string("ParticleProviderEllipse").append(suffix); - reg.add_class_(name, grp) - .template add_constructor("") - .add_method("print", &T::print) - .add_method("add", &T::add) - .add_method("add_moving", &T::add_moving) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "ParticleProviderEllipse", tag); - } -/* - // DiffusionInterfaceProvider - { - typedef MovingInterfaceBase::DiffusionInterfaceProvider T; - string name = string("DiffusionInterfaceProvider").append(suffix); - reg.add_class_(name, grp) - .template add_constructor("") - .add_method("print", &T::print) - .add_method("add", &T::add) - .set_construct_as_smart_pointer(true); - reg.add_class_to_group(name, "DiffusionInterfaceProvider", tag); - } - */ - -} - - -static void Common(Registry& reg, string grp) -{ - // write numbers into file - /* TODO: obsolete / replace by lua code */ - { - //reg.add_function("writeNumbers", static_cast(&writeNumbers), grp); - } - // write numbers into file - /* TODO: obsolete / replace by lua code */ - { - //reg.add_function("clearFile", static_cast(&clearFile), grp); - } -} - -}; // end Functionality -} // end namespace ParticleLadenFlow - - -/** - * This function is called when the plugin is loaded. - */ -void Init___ParticleLadenFlow(Registry* reg, string grp) -{ - grp.append("SpatialDisc/NavierStokes/"); - typedef ParticleLadenFlow::FunctionalityIncomp Functionality; - - try{ - RegisterDimension2d3dDependent(*reg,grp); - RegisterDomain2d3dDependent(*reg,grp); - RegisterDomain2d3dAlgebraDependent(*reg,grp); - -// RegisterAlgebraDependent(*reg,grp); - - } - UG_REGISTRY_CATCH_THROW(grp); -} - - - -}// namespace ug - - diff --git a/upwind.cpp b/upwind.cpp index 3b9d050..e1876a0 100644 --- a/upwind.cpp +++ b/upwind.cpp @@ -126,6 +126,39 @@ compute(const HCRFVGeometry* geo, } } } + + + template + template +void +NavierStokesNoUpwind:: +compute(const DimFV1FTGeometry >* geo, + const MathVector vIPVel[maxNumSCVF], + number vUpShapeSh[maxNumSCVF][maxNumSH], + number vUpShapeIp[maxNumSCVF][maxNumSCVF], + number vConvLength[maxNumSCVF]) +{ + // set shapes + for(size_t ip = 0; ip < geo->num_scvf(); ++ip) + { + // get SubControlVolumeFace + const typename DimFV1FTGeometry >::SCVF& scvf = geo->scvf(ip); + + for(size_t sh = 0; sh < scvf.num_sh(); ++sh) + { + // set upwind shape + vUpShapeSh[ip][sh] = scvf.shape(sh); + } + // compute convection length + // \todo: (optional) A convection length is not really defined for no upwind. + // but in the computation of a stabilization the term cancels, so + // we only have to ensure that the conv_lengh is non-zero + vConvLength[ip] = 1.0; + + } + +} + ///////////////////////////////////////////////////////////////////////////// // Full Upwind ///////////////////////////////////////////////////////////////////////////// diff --git a/upwind.h b/upwind.h index 51a501e..bfbeb1a 100644 --- a/upwind.h +++ b/upwind.h @@ -58,7 +58,8 @@ class NavierStokesNoUpwind : public INavierStokesUpwind, public NavierStokesUpwindRegister >, public NavierStokesUpwindRegister >, - public NavierStokesUpwindRegister > + public NavierStokesUpwindRegister >, + public NavierStokesUpwindRegisterDim >, dim, NavierStokesNoUpwind > { public: typedef INavierStokesUpwind base_type; @@ -92,6 +93,14 @@ class NavierStokesNoUpwind number vUpShapeSh[maxNumSCVF][maxNumSH], number vUpShapeIp[maxNumSCVF][maxNumSCVF], number vConvLength[maxNumSCVF]); + + /// update of values for DimFV1FTGeometry + template + static void compute(const DimFV1FTGeometry >* geo, + const MathVector vIPVel[maxNumSCVF], + number vUpShapeSh[maxNumSCVF][maxNumSH], + number vUpShapeIp[maxNumSCVF][maxNumSCVF], + number vConvLength[maxNumSCVF]); }; ///////////////////////////////////////////////////////////////////////////// From 1e7026a54a8cb444e38e6ddf35c01692f7cc5f38 Mon Sep 17 00:00:00 2001 From: Jonas Simon Date: Wed, 29 Jul 2020 09:47:17 +0200 Subject: [PATCH 3/5] fixed an error in the time part of the Navier Stokes equation. The absolute mass has to be used instead of the effective mass. --- .../fv1/moving_particle/loc_to_glob_mapper_particle_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h index fc5ebc5..5bbfae2 100644 --- a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h +++ b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h @@ -1198,7 +1198,7 @@ add_mass_part_def(vector_type& vec,std::vector transInd, std::vectorget_density(prtIndex)*volume; const number momOfInertia = MomOfInertia(levIndex, prtIndex, volume); MathVector < 2 > vScaleMass; vScaleMass[0] = 1.0; From fd8927ce32c59adb0b70a80e5eb94fc6d35b3d0e Mon Sep 17 00:00:00 2001 From: Jonas Simon Date: Wed, 29 Jul 2020 10:48:22 +0200 Subject: [PATCH 4/5] Automated applying repulsive forces. Additionally some minor fixes of names in the corresponding functions are applied. --- .../loc_to_glob_mapper_particle.h | 4 +- .../loc_to_glob_mapper_particle_impl.h | 97 ++---- .../fv1/moving_particle/moving_particle.h | 6 +- .../moving_particle/moving_particle_impl.h | 315 +++++++++++------- 4 files changed, 237 insertions(+), 185 deletions(-) diff --git a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h index 835947a..f06e030 100644 --- a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h +++ b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle.h @@ -272,7 +272,7 @@ class ParticleMapper : public IInterfaceMapper {m_bRepulsiveForce = repulsive; m_repulsiveForce = forceValue;} void set_glowinski_repulsive_force(bool repulsive, number rho, number epsilon) {m_bGlowRepulsiveForce = repulsive; m_rho = rho; m_epsilon = epsilon;} - void set_minimum_correction_force(bool repulsive, number equiDist) + void set_minimum_correction_force(bool repulsive, std::vector > equiDist) {m_bMinimumCorrectionForce = repulsive; m_repulsiveDistance = equiDist;} void set_bUsualAss(bool UsualAss) { m_bUsualAss = UsualAss; } @@ -392,7 +392,7 @@ class ParticleMapper : public IInterfaceMapper number m_rho; number m_epsilon; number m_repulsiveForce; - number m_repulsiveDistance; + std::vector > m_repulsiveDistance; // used within 'set_gravitational_rhs()' for computation of rhs number m_dt; // default = 0.0; diff --git a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h index 5bbfae2..6c9ca42 100644 --- a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h +++ b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h @@ -959,22 +959,17 @@ add_minimum_correction_force_rhs(vector_type& vec,std::vector transInd //////////////////////////////////////////////////////////////// // compute repulsive force: //////////////////////////////////////////////////////////////// - // if (!m_spCutElementHandler->valid_prt_information(i)) { - // return; - // } - for (size_t i = 0; i < num_particles(); ++i) { - if (!m_bGlowRepulsiveForce && ((int)i != prtIndex)) { - // Do not calc force with outdated particle informations - - if ((int)i == prtIndex) {continue;} - // Get particle values + if (!m_bGlowRepulsiveForce && (i != prtIndex)) { + + if (i == prtIndex) {continue;} + // Get particle values MathVector center_i = m_spCutElementHandler->get_center(i); MathVector center_prtIndex = m_spCutElementHandler->get_center(prtIndex); double Mass_i = Mass(levIndex,i); double Mass_prtIndex = Mass(levIndex,prtIndex); - - // Calculate distance vector between center points + + // Calculate distance vector between center points double dist = 0; for (size_t d = 0; d < dim; ++d){ dist += (center_i[d]-center_prtIndex[d])*(center_i[d]-center_prtIndex[d]); @@ -990,66 +985,41 @@ add_minimum_correction_force_rhs(vector_type& vec,std::vector transInd UG_LOG("distanceVec is ("<< distanceVec[0] <<","<< distanceVec[1] <<","<< distanceVec[2] <<").\n"); } } - - // Calculate force - double force = (Mass_i+Mass_prtIndex)/2*981/(m_epsilon); + + // Calculate force + double force = (Mass_i+Mass_prtIndex)/2*m_gravityConst/(m_epsilon); double max1 = std::max(0.0,-(dist-m_spCutElementHandler->get_radius(i)-m_spCutElementHandler->get_radius(prtIndex)-m_rho)/(m_rho)); force *= pow(max1,2); - - // Scale with time step + + // Scale with time step number timeScale = 1.0; if (is_time_dependent()) { timeScale = m_dt; force *= timeScale; } - - // UG_LOG("Max/original force is " << force << ".\n"); + if (m_bForceLog) { UG_LOG("Unscaled Max/original repulsive force is "< center_i = m_spCutElementHandler->get_center(i); - MathVector center_prtIndex = m_spCutElementHandler->get_center(prtIndex); - double Mass_i = Mass(levIndex,i); - double Mass_prtIndex = Mass(levIndex,prtIndex); - - // Calculate distance vector between center points - double dist = 0; - for (size_t d = 0; d < dim; ++d){ - dist += (center_i[d]-center_prtIndex[d])*(center_i[d]-center_prtIndex[d]); - } - dist = sqrt(dist); - MathVector distanceVec = center_prtIndex; - distanceVec -= center_i; - distanceVec /= dist; - - double Delta_r = m_repulsiveDistance; - double force = Mass_i/(Mass_i+Mass_prtIndex)*Delta_r/2 * 1/(m_dt*m_dt); - // double force = Delta_r/2 * 1/(m_rho*m_rho); - - - // Scale with time step - number timeScale = 1.0; - if (is_time_dependent()) { - timeScale = m_dt; - force *= timeScale; - } - - DoFRef(vec, transInd[0]) -= Mass_prtIndex*force*distanceVec[0]; - DoFRef(vec, transInd[1]) -= Mass_prtIndex*force*distanceVec[1]; - if (dim == 3) - DoFRef(vec, transInd[2]) -= Mass_prtIndex*force*distanceVec[2]; - if (m_bForceLog) { - UG_LOG("Unscaled equivalent repulsive force is "< Delta_r = m_repulsiveDistance[prtIndex]; + MathVector force; + VecScale(force, Delta_r, 1/(m_dt*m_dt)); + + DoFRef(vec, transInd[0]) -= Mass_prtIndex*force[0]; + DoFRef(vec, transInd[1]) -= Mass_prtIndex*force[1]; + if (dim == 3) + DoFRef(vec, transInd[2]) -= Mass_prtIndex*force[2]; + if (m_bForceLog) { + UG_LOG("Unscaled equivalent repulsive force is "< void ParticleMapper:: @@ -1067,7 +1037,6 @@ add_repulsive_force_rhs(vector_type& vec, std::vector transInd, // Get particle values MathVector center_i = m_spCutElementHandler->get_center(i); MathVector center_prtIndex = m_spCutElementHandler->get_center(prtIndex); - // double Mass_i = Mass(levIndex,i); double Mass_prtIndex = Mass(levIndex,prtIndex); // Calculate distance vector between center points @@ -1093,7 +1062,9 @@ add_repulsive_force_rhs(vector_type& vec, std::vector transInd, if (dim == 3) DoFRef(vec, transInd[2]) -= Mass_prtIndex*force*distanceVec[2]; - UG_LOG("Unscaled force is set to "<< force << ".\n"); + if (m_bForceLog) { + UG_LOG("Unscaled force is set to "<< force << ".\n"); + } } } @@ -1257,18 +1228,20 @@ add_rhs(vector_type& vec, std::vector transInd, std::vector } // call assembling of repuslive force acting on prtIndex-th particle - if (m_bRepulsiveForce){ + if (m_bRepulsiveForce && m_bFlagGravity[prtIndex]){ add_repulsive_force_rhs(vec, transInd, rotInd, levIndex, prtIndex); } // call assembling of glowinski repuslive force acting on prtIndex-th particle - if (m_bGlowRepulsiveForce){ + if (m_bGlowRepulsiveForce && m_bFlagGravity[prtIndex]){ add_glowinski_repulsive_force_rhs(vec, transInd, rotInd, levIndex, prtIndex); } -// no if here because of calculations and a UG_LOG call inside the function that should be printed everytime. +// no additional if here because of calculations and a UG_LOG call inside the function that should be printed everytime. // if clause is inside the function and force is added only if m_bMaxRepulsiveForce - add_minimum_correction_force_rhs(vec, transInd, rotInd, levIndex, prtIndex); + if (m_bFlagGravity[prtIndex]) { + add_minimum_correction_force_rhs(vec, transInd, rotInd, levIndex, prtIndex); + } // call this method only ONCE!! (during 'modify_GlobalSol(): m_bFlagGravity := true) diff --git a/incompressible/fv1/moving_particle/moving_particle.h b/incompressible/fv1/moving_particle/moving_particle.h index ff0d141..b88c5e8 100644 --- a/incompressible/fv1/moving_particle/moving_particle.h +++ b/incompressible/fv1/moving_particle/moving_particle.h @@ -134,10 +134,10 @@ class MovingParticle void set_glowinski_repulsive_force(bool maxRepForce, number rho, number eps) { m_spInterfaceMapper->set_glowinski_repulsive_force(maxRepForce, rho, eps); } void set_minimum_correction_force(bool EquiRepForce, number repulsiveDistance) - { m_spInterfaceMapper->set_minimum_correction_force(EquiRepForce, repulsiveDistance); } + { UG_THROW("Function is deprecated. Please use estimate_repulsive_force_parameters to calculate and set this force."); } bool mark_collision_area(SmartPtr refiner, int level); - double estimate_repulsive_force_parameters(vector_type& u, int topLevel, double MaxElemDiameter, double deltaT); + bool estimate_repulsive_force_parameters(vector_type& u, int topLevel, double MaxElemDiameter, double deltaT); void set_forceLog(bool val) { m_spInterfaceMapper->set_forceLog(val); } void set_mpi_routine(int val){ m_spCutElementHandler->set_mpi_routine(val); } @@ -283,7 +283,7 @@ class ParticleUnificator : public parmetis::IUnificator > provider ) + void update_particles(SmartPtr > provider ) { m_vParticleCoord.clear(); diff --git a/incompressible/fv1/moving_particle/moving_particle_impl.h b/incompressible/fv1/moving_particle/moving_particle_impl.h index 9b49d04..df2a928 100644 --- a/incompressible/fv1/moving_particle/moving_particle_impl.h +++ b/incompressible/fv1/moving_particle/moving_particle_impl.h @@ -677,130 +677,209 @@ mark_collision_area(SmartPtr refiner, int leve } return elem_is_cut_by_2; } - + template -double MovingParticle:: -estimate_repulsive_force_parameters(vector_type& u, int topLevel, double maxElemDiameter, double deltaT) -{ - - // Get and synchronize velocities - const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); - - std::vector > transVel; - size_t num_particles = m_spCutElementHandler->num_particles(); - transVel.resize(num_particles); - - bool verbose = false; - MathVector transVelP; +bool MovingParticle::estimate_repulsive_force_parameters(vector_type& u, int topLevel, double maxElemDiameter, double deltaT){ + // Get and synchronize velocities + const int levIndex = get_Index(GridLevel(topLevel, GridLevel::LEVEL)); + + std::vector > transVel; + int num_particles = m_spCutElementHandler->num_particles(); + transVel.resize(num_particles); + + bool verbose = true; #ifdef UG_PARALLEL - pcl::ProcessCommunicator com; - - for (size_t p = 0; p < num_particles; ++p) { - - std::vector ElemList = - m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; - if (ElemList.size() == 0) { - for (int d = 0; d < dim; ++d) { - transVelP[d] = 0.0; - } - } else { - std::vector < DoFIndex > transInd = - m_spCutElementHandler->get_transInd(levIndex, p); - - for (int d = 0; d < dim; ++d) { - transVelP[d] = DoFRef(u, transInd[d]); - } - - } - if (verbose) { - UG_LOG(pcl::ProcRank()<< "sends (" << transVelP[0] << "," << transVelP[1] << ")\n"); - } - com.allreduce(&transVelP[0],&transVel[p][0], dim, MPI_DOUBLE, PCL_RO_SUM); - if (verbose) { - if (dim == 1) { - UG_LOG("transVel[p] = ("<< transVel[p][0] <<")\n"); - } else{ - if (dim == 2) { - UG_LOG("transVel[p] = ("<< transVel[p][0] << "," << transVel[p][1] <<")\n"); - } else { - if (dim == 3) { - UG_LOG("transVel[p] = ("<< transVel[p][0] << "," << transVel[p][1] << "," << transVel[p][2] <<")\n"); - } - } - } - } - } + pcl::ProcessCommunicator com; + + for (size_t p = 0; p < num_particles; ++p) { + MathVector transVelP; + + std::vector ElemList = + m_spCutElementHandler->m_vvvElemListCut[levIndex][p]; + if (ElemList.size() == 0) { + for (int d = 0; d < dim; ++d) { + transVelP[d] = 0.0; + } + } else { + std::vector < DoFIndex > transInd = + m_spCutElementHandler->get_transInd(levIndex, p); + + for (int d = 0; d < dim; ++d) { + transVelP[d] = DoFRef(u, transInd[d]); + } + + } + if (verbose) { + UG_LOG(pcl::ProcRank()<< "sends (" << transVelP[0] << "," << transVelP[1] << ")\n"); + } + com.allreduce(&transVelP[0],&transVel[p][0], dim, MPI_DOUBLE, PCL_RO_SUM); + if (verbose) { + if (dim == 1) { + UG_LOG("transVel[p] = ("<< transVel[p][0] <<")\n"); + } else{ + if (dim == 2) { + UG_LOG("transVel[p] = ("<< transVel[p][0] << "," << transVel[p][1] <<")\n"); + } else { + if (dim == 3) { + UG_LOG("transVel[p] = ("<< transVel[p][0] << "," << transVel[p][1] << "," << transVel[p][2] <<")\n"); + } + } + } + } + } #else - for (size_t p = 0; p < num_particles; ++p) { - std::vector < DoFIndex > transInd = - m_spCutElementHandler->get_transInd(levIndex, p); - - for (int d = 0; d < dim; ++d) { - transVelP[d] = DoFRef(u, transInd[d]); - } - } + for (size_t p = 0; p < num_particles; ++p) { + std::vector < DoFIndex > transInd = + m_spCutElementHandler->get_transInd(levIndex, p); + + for (int d = 0; d < dim; ++d) { + transVelP[d] = DoFRef(u, transInd[d]); + } + } #endif - - double eps = 0.0; - //const int levIndex = get_Index(GridLevel(13957 /*topLevel*/, GridLevel::LEVEL)); - - for (size_t p = 0; p < num_particles; ++p){ - // Get values for particle p - MathVector center_p = m_spCutElementHandler->get_center(p); - VecScaleAdd(center_p, 1.0, center_p, deltaT, transVel[p]); - number radius_p = m_spCutElementHandler->get_radius(p); - //double Mass_p = m_spInterfaceMapper->Mass(13957,p); - for (size_t q = 0; q < num_particles; ++q){ - if (p == q) { - continue; - } - if (verbose) - UG_LOG("p = "< center_q = m_spCutElementHandler->get_center(q); - VecScaleAdd(center_q, 1.0, center_q, deltaT, transVel[q]); - number radius_q = m_spCutElementHandler->get_radius(q); - //double Mass_q = m_spInterfaceMapper->Mass(13957,q); - // Calculate force - if (verbose) { - if (dim == 1) { - UG_LOG("center_p = ("<< center_p[0] <<")\n"); - } else{ - if (dim == 2) { - UG_LOG("center_p = ("<< center_p[0] << "," << center_p[1] <<")\n"); - } else { - if (dim == 3) { - UG_LOG("center_p = ("<< center_p[0] << "," << center_p[1] << "," << center_p[2] <<")\n"); - } - } - } - if (dim == 1) { - UG_LOG("center_q = ("<< center_q[0] <<")\n"); - } else{ - if (dim == 2) { - UG_LOG("center_q = ("<< center_q[0] << "," << center_q[1] <<")\n"); - } else { - if (dim == 3) { - UG_LOG("center_q = ("<< center_q[0] << "," << center_q[1] << "," << center_q[2] <<")\n"); - } - } - } - } - number centerDist = VecDistance(center_q, center_p); - if (verbose) - UG_LOG("centerDist = "<< centerDist <<"\n"); - number s_ij = centerDist - radius_p - radius_q; - if (verbose) - UG_LOG("centerDist - radius_p - radius_q = "<< s_ij <<"\n"); - number dist = maxElemDiameter - s_ij; - if (verbose) - UG_LOG("maxElemDiameter - s_ij = " << dist <<"\n"); - eps = std::max(eps,dist); + + std::vector > eps; + for (size_t i = 0; i < num_particles; ++i) { + eps.push_back(MathVector(0.0)); + } + bool conflict = true; + //const int levIndex = get_Index(GridLevel(13957 /*topLevel*/, GridLevel::LEVEL)); + + std::vector > centers; + for (size_t i = 0; i < num_particles; ++i) { + centers.push_back(m_spCutElementHandler->get_center(i)); + VecScaleAdd(centers[i], 1.0, centers[i], deltaT, transVel[i]); + } + + if (num_particles == 1) { + return false; + MathVector center_p = m_spCutElementHandler->get_center(0); + MathVector center_q; + center_q = center_p; + if (dim == 3){ + center_q[2] = m_spCutElementHandler->get_radius(0); + } else { + return false; + } + + center_p -= center_q; + UG_LOG("center diff is " << center_p << "\n"); + MathVector force; + + //VecScale(force, center_p, 1/(m_dt*m_dt)); + eps[0] = center_p; + if (center_p[2] < 0){ + if (verbose) { + UG_LOG("Giving " << eps[0] << " to set_minimum_correction_force\n"); + } + m_spInterfaceMapper->set_minimum_correction_force(true, eps); + return true; + } + return false; + } + + int iter = 25; + while (conflict && iter > 0) { + conflict = false; + std::vector > new_eps(eps); + for (size_t p = 0; p < num_particles; ++p){ + // Get values for particle p + number Mass_p = m_spInterfaceMapper->Mass(topLevel,p); + MathVector center_p; + VecAdd(center_p, centers[p], eps[p]); + number radius_p = m_spCutElementHandler->get_radius(p); + for (size_t q = 0; q < num_particles; ++q){ + if (p == q) { + continue; + } + if (verbose) + UG_LOG("p = "<Mass(topLevel,q); + MathVector center_q; + VecAdd(center_q, centers[q], eps[q]); + number radius_q = m_spCutElementHandler->get_radius(q); + + // Calculate force + if (verbose) { + if (dim == 1) { + UG_LOG("center_p = ("<< center_p[0] <<")\n"); + } else{ + if (dim == 2) { + UG_LOG("center_p = ("<< center_p[0] << "," << center_p[1] <<")\n"); + } else { + if (dim == 3) { + UG_LOG("center_p = ("<< center_p[0] << "," << center_p[1] << "," << center_p[2] <<")\n"); + } + } + } + if (dim == 1) { + UG_LOG("center_q = ("<< center_q[0] <<")\n"); + } else{ + if (dim == 2) { + UG_LOG("center_q = ("<< center_q[0] << "," << center_q[1] <<")\n"); + } else { + if (dim == 3) { + UG_LOG("center_q = ("<< center_q[0] << "," << center_q[1] << "," << center_q[2] <<")\n"); + } + } + } + } + + number centerDist = VecDistance(center_q, center_p); + if (verbose) + UG_LOG("centerDist = "<< centerDist <<"\n"); + number s_ij = centerDist - radius_p - radius_q; + if (verbose) + UG_LOG("centerDist - radius_p - radius_q = "<< s_ij <<"\n"); + UG_LOG("maxElemDiameter = "< 0.0) { + // Calculate distance vector between center points + double dist_norm = 0; + for (size_t d = 0; d < dim; ++d){ + dist_norm += (center_q[d]-center_p[d])*(center_q[d]-center_p[d]); + } + dist_norm = sqrt(dist_norm); + MathVector distanceVec = center_p; + distanceVec -= center_q; + distanceVec /= dist_norm; + + Delta_r *= Mass_q/(Mass_q+Mass_p); + + for (size_t d = 0; d < dim; ++d){ + new_eps[p][d] += 1.05*Delta_r*distanceVec[d]; + } + UG_LOG("new_eps[p]: " << new_eps[p] << "\n"); + conflict = true; + } + } + } + eps = new_eps; + iter--; + } + if (verbose) { + for (size_t i = 0; i < num_particles; ++i) { + if (dim == 2) { + UG_LOG("eps "< (" << eps[i][0] << "," << eps[i][1] << ")\n"); + } + if (dim == 3) { + UG_LOG("eps "< (" << eps[i][0] << "," << eps[i][1] << "," << eps[i][2] << ")\n"); } - } - - return eps; + } + } + for (size_t i = 0; i < num_particles; ++i) { + double vecLen = VecLengthSq(eps[i]); + if (vecLen > 1e-14 or vecLen < -1e-14) { + m_spInterfaceMapper->set_minimum_correction_force(true, eps); + return true; + } + } + return false; } #ifdef UG_PARALLEL From 8cf6ebc98211dcafb665104e03ea1cc7343934cf Mon Sep 17 00:00:00 2001 From: Jonas Simon Date: Sun, 9 Aug 2020 12:43:21 +0200 Subject: [PATCH 5/5] fixed mass calculation for jacobian (see commit 1e7026a) --- .../fv1/moving_particle/loc_to_glob_mapper_particle_impl.h | 2 +- upwind.cpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h index 6c9ca42..a0ea82d 100644 --- a/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h +++ b/incompressible/fv1/moving_particle/loc_to_glob_mapper_particle_impl.h @@ -826,7 +826,7 @@ add_mass_part_jac(matrix_type& mat, std::vector transInd, std::vector< // add mass term to global matrix (instead of using IConstraint::adjust_jacobian() ) for (int d = 0; d < dim; ++d) { - DoFRef(mat, transInd[d], transInd[d]) += Mass(levIndex, prtIndex, volume); + DoFRef(mat, transInd[d], transInd[d]) += m_spInterfaceHandlerLocal->get_density(prtIndex)*volume; // for dim = 2: the second DoF of rotInd is unused! if (dim == 3 || d == 0) DoFRef(mat, rotInd[d], rotInd[d]) += MomOfInertia(levIndex, prtIndex, volume); diff --git a/upwind.cpp b/upwind.cpp index e1876a0..4ebf7d4 100644 --- a/upwind.cpp +++ b/upwind.cpp @@ -783,6 +783,11 @@ compute(const DimFV1FTGeometry >* g continue; } + if ((vIPVel[ip][0] != vIPVel[ip][0]) || (vIPVel[ip][1] != vIPVel[ip][1]) || (vIPVel[ip][2] != vIPVel[ip][2])) { + vConvLength[ip] = 1.0; + continue; + } + // side and intersection vectors static const int refDim = TFVGeom::dim; size_t side = 0;