Skip to content

Implementing Surface-directed spinodal decomposition

OpenLB – Open Source Lattice Boltzmann Code Forums on OpenLB General Topics Implementing Surface-directed spinodal decomposition

Viewing 13 posts - 1 through 13 (of 13 total)
  • Author
    Posts
  • #7123
    syed
    Participant

    Hello developers, I am trying to set up forcedshanchen interaction between the solid boundary and one of my components in a two-component system. I have already written the Spinodal decomposition application and am now trying to induce wetting by a component at the bottom surface.
    How can I implement this using the Shan-Chen interaction potential?

    #7124
    syed
    Participant

    I am just thinking of how to couple ForcedShanchen dynamics between fluid and the boundary (different material numbers). I did it for fluid(A)-fluid(B). I want interaction potential between fluid and the boundary of the form = = G*Ψ(x)*s(x + e)e, where s is 1 if (x+e) is a wall boundary node and 0 otherwise.

    #7125
    mathias
    Keymaster

    Usually you just set a particular density for both lattices seperatly but also your idea could be realised in a e.g. new postProcessor.

    #7126
    syed
    Participant

    Thank you Mathias for your reply. I see that I have to write a post-processor which will be integrated after the streaming process. Do I have to write it from scratch or do we have any such post-processor where I can just manipulate or insert the above-mentioned coupling?

    #7127
    mathias
    Keymaster

    I would copy-paste, rename and edit an existing one..

    #7129
    syed
    Participant

    I can find the one to edit, but can you suggest which one will be better? This will make my task more manageable. Thanking you in advance.

    #7170
    syed
    Participant

    Dear developers,
    I am trying to write the post-processor for the boundary where I wanted to couple the ghost nodes with the nearest fluid with a pseudopotential of F=g(x)Ψ(x)s(x + e)e, where e is the discrete velocity and s(x+e) is 1 if x+e lies on the wall and 0 otherwise. I will substitute a constant for g(x).
    So, my plan to implement this boundary is to write a post-processor, just like setFreeEnergyWall. Am I correct? Is this way to add the force F to my lattice points near the wall, and will this force be added to the collision term?
    My work plan is as such:
    1. Create Descriptor that holds additional fields (external F, velocity, Omega)
    2. Prepare geometry (two Slatttices with 1 as fluid and 2 & 3 boundary material)
    3. Patching dynamics to the fluid of Slattices (ForcedShanChen)
    4. Creating coupling between Slattices (ShanChen pseudopotential)
    5. Patching dynamics to boundaries (Upper wall only bounce-back)
    6. Patching dynamics to boundaries (Lower wall bounce-back + Force described above)
    7. Initialize lattice points with values
    8. Collide&Stream
    9. communication inter-Slattices
    9. Execute coupling of point 4.

    Am I correct about the concepts? Adding postprocessor for wall and fluid nodes will add the F values to its dynamics and will be taken care in collide & stream?

    #7182
    Adrian
    Keymaster

    Yes, you can write a new post processor to do that. Your outlined approach looks workable.

    However, I would suggest to not use the legacy (non-GPU-supported) post processors used by setFreeEnergyWallBoundary as a blueprint but e.g. the style used in setInterpolatedVelocityBoundary. Such a new post processor is more simple and runs on all supported platforms with good performance:

    
    struct ExamplePostProcessor {
      static constexpr OperatorScope scope = OperatorScope::PerCell;
    
      int getPriority() const {
        return 0;
      }
    
      template <typename CELL>
      void apply(CELL& cell) any_platform {
        // do something with the cell
        // neighbors can be accessed via <code>cell.neighbor(c_i)</code>
      }
    };
    
    #7184
    Adrian
    Keymaster

    On the dynamics: Dynamics don’t store data, they only model how the momenta are computed and the collision is performed.

    You can set the population iPop of a “ghost” neighbor cell (commonly being assigned NoDynamics, meaning they don’t perform any collision) in direction c to value using e.g. cell.neighbor(c)[iPop] = value;. This will happen after the streaming step for normal post processors. If you need to execute this at a different time this is also straight forward to do as post processors are assigned to and executed at various stages in OpenLB.

    #7192
    syed
    Participant

    Thank You, Adrian, for such an elaborate response. It will take some time and practice to comprehend the exact work.
    As a second idea, I was thinking to implement the attractive force exerted by the wall (1/z^3) as an external force in the descriptor and the boundary will purely bounce back. It is possible? This way I might avoid writing my own post-processor for now, which I will surely write in some time. So do we have any analytical functor where I can add this z-dependent function as an external function to both of my lattices? Just like gravity in the rayleigh instability application.
    And secondly, can we add thermal noise to our application? do we have this kind of dynamic also?

    #7206
    FBukreev
    Keymaster

    Hello,

    you can write your own analytical function that depends on the z coordinate and then define the force with that functor. Here one example.

    template <typename T, typename S, typename DESCRIPTOR>
        class PorosityProfil3D : public AnalyticalF3D<T, S>
        {
        private:
            T x0, x1, y0, y1, z0, z1, u_p;
            UnitConverter<T, DESCRIPTOR> const &converter;
            int iT, tempCase;
    
        public:
            PorosityProfil3D(T x0_, T x1_, T y0_, T y1_, T z0_, T z1_, T u_p_, int iT_, int tempCase_, UnitConverter<T, DESCRIPTOR> const &converter_) : AnalyticalF3D<T, S>(3),
                                                                                                                            x0(x0_), x1(x1_), y0(y0_), y1(y1_), z0(z0_), z1(z1_), u_p(u_p_), iT(iT_), tempCase(tempCase_), converter(converter_)
            {
                this->getName() = "PorosityProfil3D";
            };
    
            bool operator()(T output[1], const S x[3])
            {
                T res = converter.getResolution();
                T gf = res / (res + 1);
                T distX = 2 * M_PI * (x[0] - tempCase * u_p * converter.getPhysTime(iT) - x0) / (x1 - x0) * gf;
                T distY = 2 * M_PI * (x[1] - tempCase * u_p * converter.getPhysTime(iT) - y0) / (y1 - y0) * gf;
                T distZ = 2 * M_PI * (x[2] - tempCase * u_p * converter.getPhysTime(iT) - y0) / (z1 - z0) * gf;
    
                output[0] = 0.5 + 0.4 * util::sin(distX) * util::sin(distY) * util::sin(distZ);
    
                return true;
            };
        };
    

    the x[2] is the z variable. For the force you need to change output[1] to the 3 dimensional output[3] array.

    What do you mean under thermal noise? You can add advection diffusion equation for temperature scalar and couple it to the main equations.

    Greetings
    Fedor

    #7250
    syed
    Participant

    Thank you fedor for your reply. is this example that you gave is present in current open LB version ? I am searching for this porosity profil3D . But 2 am not able to find it . will you please help.

    #7252
    FBukreev
    Keymaster

    You can find something similar in the turbulent nozzle3d example. There is a turbulent inket velocity functor. What I wrote above is an example not from some specific case.

Viewing 13 posts - 1 through 13 (of 13 total)
  • You must be logged in to reply to this topic.