|
1 | 1 | #ifndef COLLOCATIONINTEGRATOR_HPP |
2 | 2 | #define COLLOCATIONINTEGRATOR_HPP |
3 | 3 |
|
| 4 | +#include <cmath> |
| 5 | +#include <functional> |
4 | 6 | #include <iosfwd> |
5 | | -#include <tuple> |
| 7 | +#include <stdexcept> |
6 | 8 |
|
7 | 9 | #include "Config.hpp" |
8 | 10 |
|
9 | 11 | #include <Eigen/Dense> |
10 | 12 |
|
11 | | -#include "DerivativeTypes.hpp" |
12 | | -#include "AnisotropicLiquid.hpp" |
| 13 | +#include "IntegratorHelperFunctions.hpp" |
13 | 14 | #include "Element.hpp" |
| 15 | +#include "AnisotropicLiquid.hpp" |
14 | 16 | #include "IonicLiquid.hpp" |
15 | 17 | #include "SphericalDiffuse.hpp" |
16 | 18 | #include "UniformDielectric.hpp" |
17 | 19 | #include "Vacuum.hpp" |
18 | 20 |
|
19 | 21 | /*! \file CollocationIntegrator.hpp |
20 | | - * \class CollocationIntegrator |
21 | | - * \brief Implementation of diagonal elements of S and D using approximate collocation |
| 22 | + * \struct CollocationIntegrator |
| 23 | + * \brief Implementation of the single and double layer operators matrix representation using one-point collocation |
22 | 24 | * \author Roberto Di Remigio |
23 | | - * \date 2014 |
| 25 | + * \date 2015 |
24 | 26 | * |
25 | 27 | * Calculates the diagonal elements of S as: |
26 | 28 | * \f[ |
|
32 | 34 | * \f] |
33 | 35 | */ |
34 | 36 |
|
35 | | -template <typename DerivativeTraits, |
36 | | - typename ProfilePolicy> |
| 37 | +using std::placeholders::_1; |
| 38 | +using std::placeholders::_2; |
| 39 | +using std::placeholders::_3; |
| 40 | +using integrator::KernelS; |
| 41 | +using integrator::KernelD; |
| 42 | + |
37 | 43 | struct CollocationIntegrator |
38 | 44 | { |
39 | 45 | CollocationIntegrator() : factor_(1.07) {} |
40 | 46 | ~CollocationIntegrator() {} |
41 | 47 |
|
42 | | - double computeS(const Vacuum<DerivativeTraits, CollocationIntegrator> & /* gf */, const Element & e) const { |
43 | | - double area = e.area(); |
44 | | - return (factor_ * std::sqrt(4 * M_PI / area)); |
| 48 | + /**@{ Single and double layer potentials for a Vacuum Green's function by collocation */ |
| 49 | + template <typename DerivativeTraits> |
| 50 | + Eigen::MatrixXd singleLayer(const Vacuum<DerivativeTraits, CollocationIntegrator> & gf, const std::vector<Element> & e) const { |
| 51 | + auto f = this->factor_; |
| 52 | + auto diagonal = [f] (double area) -> double { return (f * std::sqrt(4 * M_PI / area)); }; |
| 53 | + KernelS kernelS = std::bind(&Vacuum<DerivativeTraits, CollocationIntegrator>::kernelS, gf, _1, _2); |
| 54 | + return integrator::singleLayer(e, diagonal, kernelS); |
45 | 55 | } |
46 | | - double computeD(const Vacuum<DerivativeTraits, CollocationIntegrator> & /* gf */, const Element & e) const { |
47 | | - double area = e.area(); |
48 | | - double radius = e.sphere().radius(); |
49 | | - return (-factor_ * std::sqrt(M_PI/ area) * (1.0 / radius)); |
| 56 | + template <typename DerivativeTraits> |
| 57 | + Eigen::MatrixXd doubleLayer(const Vacuum<DerivativeTraits, CollocationIntegrator> & gf, const std::vector<Element> & e) const { |
| 58 | + auto f = this->factor_; |
| 59 | + auto diagonal = [f] (double area, double radius) -> double { return (-f * std::sqrt(M_PI/ area) * (1.0 / radius)); }; |
| 60 | + KernelD kernelD = std::bind(&Vacuum<DerivativeTraits, CollocationIntegrator>::kernelD, gf, _1, _2, _3); |
| 61 | + return integrator::doubleLayer(e, diagonal, kernelD); |
50 | 62 | } |
51 | | - |
52 | | - double computeS(const UniformDielectric<DerivativeTraits, CollocationIntegrator> & gf, const Element & e) const { |
53 | | - double epsInv = 1.0 / gf.epsilon(); |
54 | | - double area = e.area(); |
55 | | - return (factor_ * std::sqrt(4 * M_PI / area) * epsInv); |
| 63 | + /**@}*/ |
| 64 | + |
| 65 | + /**@{ Single and double layer potentials for a UniformDielectric Green's function by collocation */ |
| 66 | + template <typename DerivativeTraits> |
| 67 | + Eigen::MatrixXd singleLayer(const UniformDielectric<DerivativeTraits, CollocationIntegrator> & gf, const std::vector<Element> & e) const { |
| 68 | + auto f = this->factor_; |
| 69 | + auto epsInv = 1.0 / gf.epsilon(); |
| 70 | + auto diagonal = [f, epsInv] (double area) -> double { return (f * std::sqrt(4 * M_PI / area) * epsInv); }; |
| 71 | + KernelS kernelS = std::bind(&UniformDielectric<DerivativeTraits, CollocationIntegrator>::kernelS, gf, _1, _2); |
| 72 | + return integrator::singleLayer(e, diagonal, kernelS); |
56 | 73 | } |
57 | | - double computeD(const UniformDielectric<DerivativeTraits, CollocationIntegrator> & /* gf */, const Element & e) const { |
58 | | - double area = e.area(); |
59 | | - double radius = e.sphere().radius(); |
60 | | - return (-factor_ * std::sqrt(M_PI/ area) * (1.0 / radius)); |
| 74 | + template <typename DerivativeTraits> |
| 75 | + Eigen::MatrixXd doubleLayer(const UniformDielectric<DerivativeTraits, CollocationIntegrator> & gf, const std::vector<Element> & e) const { |
| 76 | + auto f = this->factor_; |
| 77 | + auto diagonal = [f] (double area, double radius) -> double { return (-f * std::sqrt(M_PI/ area) * (1.0 / radius)); }; |
| 78 | + KernelD kernelD = std::bind(&UniformDielectric<DerivativeTraits, CollocationIntegrator>::kernelD, gf, _1, _2, _3); |
| 79 | + return integrator::doubleLayer(e, diagonal, kernelD); |
61 | 80 | } |
| 81 | + /**@}*/ |
62 | 82 |
|
63 | | - double computeS(const IonicLiquid<DerivativeTraits, CollocationIntegrator> & /* gf */, const Element & /* e */) const { |
64 | | - return 1.0; |
| 83 | + /**@{ Single and double layer potentials for a IonicLiquid Green's function by collocation */ |
| 84 | + template <typename DerivativeTraits> |
| 85 | + Eigen::MatrixXd singleLayer(const IonicLiquid<DerivativeTraits, CollocationIntegrator> & /* gf */, const std::vector<Element> & /* e */) const { |
| 86 | + throw std::runtime_error("Not implemented yet!"); |
65 | 87 | } |
66 | | - double computeD(const IonicLiquid<DerivativeTraits, CollocationIntegrator> & /* gf */, const Element & /* e */) const { |
67 | | - return 1.0; |
| 88 | + template <typename DerivativeTraits> |
| 89 | + Eigen::MatrixXd doubleLayer(const IonicLiquid<DerivativeTraits, CollocationIntegrator> & /* gf */, const std::vector<Element> & /* e */) const { |
| 90 | + throw std::runtime_error("Not implemented yet!"); |
68 | 91 | } |
| 92 | + /**@}*/ |
69 | 93 |
|
70 | | - double computeS(const AnisotropicLiquid<DerivativeTraits, CollocationIntegrator> & /* gf */, const Element & /* e */) const { |
71 | | - return 1.0; |
| 94 | + /**@{ Single and double layer potentials for an AnisotropicLiquid Green's function by collocation */ |
| 95 | + template <typename DerivativeTraits> |
| 96 | + Eigen::MatrixXd singleLayer(const AnisotropicLiquid<DerivativeTraits, CollocationIntegrator> & /* gf */, const std::vector<Element> & /* e */) const { |
| 97 | + throw std::runtime_error("Not implemented yet!"); |
72 | 98 | } |
73 | | - double computeD(const AnisotropicLiquid<DerivativeTraits, CollocationIntegrator> & /* gf */, const Element & /* e */) const { |
74 | | - return 1.0; |
| 99 | + template <typename DerivativeTraits> |
| 100 | + Eigen::MatrixXd doubleLayer(const AnisotropicLiquid<DerivativeTraits, CollocationIntegrator> & /* gf */, const std::vector<Element> & /* e */) const { |
| 101 | + throw std::runtime_error("Not implemented yet!"); |
75 | 102 | } |
76 | | - |
77 | | - double computeS(const SphericalDiffuse<CollocationIntegrator, ProfilePolicy> & gf, const Element & e) const { |
78 | | - // The singular part is "integrated" as usual, while the nonsingular part is evaluated in full |
79 | | - double area = e.area(); |
80 | | - // Diagonal of S inside the cavity |
81 | | - double Sii_I = factor_ * std::sqrt(4 * M_PI / area); |
82 | | - // "Diagonal" of Coulomb singularity separation coefficient |
83 | | - double coulomb_coeff = gf.coefficientCoulomb(e.center(), e.center()); |
84 | | - // "Diagonal" of the image Green's function |
85 | | - double image = gf.imagePotential(e.center(), e.center()); |
86 | | - |
87 | | - return (Sii_I / coulomb_coeff + image); |
| 103 | + /**@}*/ |
| 104 | + |
| 105 | + /**@{ Single and double layer potentials for a SphericalDiffuse Green's function by collocation */ |
| 106 | + template <typename ProfilePolicy> |
| 107 | + Eigen::MatrixXd singleLayer(const SphericalDiffuse<CollocationIntegrator, ProfilePolicy> & /* gf */, const std::vector<Element> & e) const { |
| 108 | +// // The singular part is "integrated" as usual, while the nonsingular part is evaluated in full |
| 109 | +// double area = e.area(); |
| 110 | +// // Diagonal of S inside the cavity |
| 111 | +// double Sii_I = factor_ * std::sqrt(4 * M_PI / area); |
| 112 | +// // "Diagonal" of Coulomb singularity separation coefficient |
| 113 | +// double coulomb_coeff = gf.coefficientCoulomb(e.center(), e.center()); |
| 114 | +// // "Diagonal" of the image Green's function |
| 115 | +// double image = gf.imagePotential(e.center(), e.center()); |
| 116 | + |
| 117 | +// return (Sii_I / coulomb_coeff + image); |
| 118 | + return Eigen::MatrixXd::Zero(e.size(), e.size()); |
88 | 119 | } |
89 | | - double computeD(const SphericalDiffuse<CollocationIntegrator, ProfilePolicy> & gf, const Element & e) const { |
90 | | - // The singular part is "integrated" as usual, while the nonsingular part is evaluated in full |
91 | | - double area = e.area(); |
92 | | - double radius = e.sphere().radius(); |
93 | | - // Diagonal of S inside the cavity |
94 | | - double Sii_I = factor_ * std::sqrt(4 * M_PI / area); |
95 | | - // Diagonal of D inside the cavity |
96 | | - double Dii_I = -factor_ * std::sqrt(M_PI/ area) * (1.0 / radius); |
97 | | - // "Diagonal" of Coulomb singularity separation coefficient |
98 | | - double coulomb_coeff = gf.coefficientCoulomb(e.center(), e.center()); |
99 | | - // "Diagonal" of the directional derivative of the Coulomb singularity separation coefficient |
100 | | - double coeff_grad = gf.coefficientCoulombDerivative(e.normal(), e.center(), e.center()) / std::pow(coulomb_coeff, 2); |
101 | | - // "Diagonal" of the directional derivative of the image Green's function |
102 | | - double image_grad = gf.imagePotentialDerivative(e.normal(), e.center(), e.center()); |
103 | | - |
104 | | - double eps_r2 = 0.0; |
105 | | - std::tie(eps_r2, std::ignore) = gf.epsilon(e.center()); |
106 | | - |
107 | | - return eps_r2 * (Dii_I / coulomb_coeff - Sii_I * coeff_grad + image_grad); |
| 120 | + template <typename ProfilePolicy> |
| 121 | + Eigen::MatrixXd doubleLayer(const SphericalDiffuse<CollocationIntegrator, ProfilePolicy> & /* gf */, const std::vector<Element> & e) const { |
| 122 | +// // The singular part is "integrated" as usual, while the nonsingular part is evaluated in full |
| 123 | +// double area = e.area(); |
| 124 | +// double radius = e.sphere().radius(); |
| 125 | +// // Diagonal of S inside the cavity |
| 126 | +// double Sii_I = factor_ * std::sqrt(4 * M_PI / area); |
| 127 | +// // Diagonal of D inside the cavity |
| 128 | +// double Dii_I = -factor_ * std::sqrt(M_PI/ area) * (1.0 / radius); |
| 129 | +// // "Diagonal" of Coulomb singularity separation coefficient |
| 130 | +// double coulomb_coeff = gf.coefficientCoulomb(e.center(), e.center()); |
| 131 | +// // "Diagonal" of the directional derivative of the Coulomb singularity separation coefficient |
| 132 | +// double coeff_grad = gf.coefficientCoulombDerivative(e.normal(), e.center(), e.center()) / std::pow(coulomb_coeff, 2); |
| 133 | +// // "Diagonal" of the directional derivative of the image Green's function |
| 134 | +// double image_grad = gf.imagePotentialDerivative(e.normal(), e.center(), e.center()); |
| 135 | + |
| 136 | +// double eps_r2 = 0.0; |
| 137 | +// std::tie(eps_r2, std::ignore) = gf.epsilon(e.center()); |
| 138 | + |
| 139 | +// return eps_r2 * (Dii_I / coulomb_coeff - Sii_I * coeff_grad + image_grad); |
| 140 | + return Eigen::MatrixXd::Zero(e.size(), e.size()); |
108 | 141 | } |
| 142 | + /**@}*/ |
109 | 143 |
|
110 | 144 | /// Scaling factor for the collocation formulas |
111 | 145 | double factor_; |
|
0 commit comments