FBPINNs icon indicating copy to clipboard operation
FBPINNs copied to clipboard

Wavefield "c" Value

Open ShaikhaTheGreen opened this issue 2 years ago • 3 comments

Dear Ben,

Thank you for this creative work! I saw in the code that you can use two types of c values; one is obtained by _constant_c() and the other by _gaussian_c(). I understand the conceptual difference between them, but I wonder if I wanted to test a two wavefeild with two values of c (e.g.: c1 and c2) how can I write a function to do that?

My initial attempt was to write:

def _variable_c(x):
        "Defines a variable velocity model"
        return ((np.tanh(80*(x-2.5))+5)/4) * torch.ones((x.shape[0],1), dtype=x.dtype, device= x.device) 

I then use this assignment:

 c = _variable_c 
 c = c(torch.from_numpy(np.stack([xx,yy],-1).reshape((NX*NY,2)))).numpy().reshape(NX,NY)

The idea that I'm trying to achieve is to assign the value of c=1 to x<2.5 and c=1.5 to x>2.5 by using the "tanh" function for a smooth transition of c value. I'm getting this error:

~\AppData\Local\Temp/ipykernel_16716/2797370787.py in exact_solution(x, batch_size)
     51 
     52         c = _variable_c #_constant_c
---> 53         c = c(torch.from_numpy(np.stack([xx,yy],-1).reshape((NX*NY,2)))).numpy().reshape(NX,NY)
     54         #c(c0,torch.from_numpy(np.stack([xx,yy],-1).reshape((NX*NY,2)))).numpy().reshape(NX,NY)
     55 

ValueError: cannot reshape array of size 2000000 into shape (1000,1000)

Any ideas on how to achieve this and get around the error?

ShaikhaTheGreen avatar Feb 01 '23 22:02 ShaikhaTheGreen

Hi @engsbk, please check out the latest FBPINN release - it is a major update and this should be easily implementable with the new fbpinns.problems.Problem class. Something like this:

import jax.numpy as jnp
import numpy as np

from fbpinns.domains import RectangularDomainND
from fbpinns.problems import WaveEquationConstantVelocity3D
from fbpinns.networks import FCN
from fbpinns.constants import Constants
from fbpinns.trainers import PINNTrainer


class WaveEquationInterfaceVelocity3D(WaveEquationConstantVelocity3D):

    @staticmethod
    def init_params(c0=1, c1=2,
                    source=np.array([[-0.5, 0., 0.1, 1.]])):

        static_params = {
            "dims":(1,3),
            "c0":c0,
            "c1":c1,
            "c_fn":WaveEquationInterfaceVelocity3D.c_fn,# velocity function
            "source":jnp.array(source),# location, width and amplitude of initial gaussian sources (k, 4)
            }
        return static_params, {}
    
    @staticmethod
    def c_fn(all_params, x_batch):
        "Computes the velocity model"
        
        p = all_params["static"]["problem"]
        c0, c1 = p["c0"], p["c1"]
        
        x = x_batch[:,0:1]
        c = c0 + (c1-c0)*(1+jnp.tanh(x/0.1))/2
        
        return c

c = Constants(
    domain=RectangularDomainND,
    domain_init_kwargs=dict(
        xmin=np.array([-1,-1,0]),
        xmax=np.array([1,1,1]),
    ),
    problem=WaveEquationInterfaceVelocity3D,
    problem_init_kwargs=dict(
        c0=1, 
        c1=2,
    ),
    network=FCN,
    network_init_kwargs=dict(
        layer_sizes=[3,32,32,32,1],
    ),
    decomposition_init_kwargs=dict(
        unnorm=(0.,0.1),
    ),
    ns=((50,50,50),),
    n_test=(100,100,5),
    n_steps=15000,
    clear_output=True,
)

run = PINNTrainer(c)
_ = run.train()

image

benmoseley avatar Jul 31 '23 16:07 benmoseley

can this problem use subdomain scheduling and how? I refered to the code presented in the example 3 but failed. scheduler = LineSchedulerRectangularND, scheduler_kwargs = dict( point=[0.], iaxis=0, ),

WeCcRy avatar Jul 07 '24 12:07 WeCcRy

Yes, but this is a 2+1D equation so you probably want to use a schedulers.PlaneSchedulerRectangularND instead of a LineSchedulerRectangularND

benmoseley avatar Jul 10 '24 10:07 benmoseley