Giter VIP home page Giter VIP logo

neuralsolvers's Introduction

Introduction

Neural Solvers are neural network based solver for partial differential equations and inverse problems. The framework implements the physics-informed neural network approach on scale. Physics informed neural networks allow strong scaling by design. Therefore, we have developed a framework that uses data parallelism to accelerate the training of physics informed neural networks significantly. To implement data parallelism, we use the Horovod framework, which provides near-ideal speedup on multi-GPU regimes.

More details about our framework you can find in our recent publication:

P. Stiller, F. Bethke, M. Böhme, R. Pausch, S. Torge, A. Debus, J. Vorberger, M.Bussmann, N. Hoffmann: 
Large-scale Neural Solvers for Partial Differential Equations (2020).

Implemented Approaches:

  • P. Stiller, F. Bethke, M. Böhme, R. Pausch, S. Torge, A. Debus, J. Vorberger, M.Bussmann, N. Hoffmann: Large-scale Neural Solvers for Partial Differential Equations (2020).

  • Raissi, Maziar, Paris Perdikaris, and George Em Karniadakis. Physics Informed Deep Learning (Part I): Data-driven Solutions of Nonlinear Partial Differential Equations.(2017).

  • Raissi, Maziar, Paris Perdikaris, and George Em Karniadakis. Physics Informed Deep Learning (Part II): Data-driven Discovery of Nonlinear Partial Differential Equations.(2017).

  • Suryanarayana Maddu, Dominik Sturm, Christian L. Müller and Ivo F. Sbalzarini (2021): Inverse Dirichlet Weighting Enables Reliable Training of Physics Informed Neural Networks

  • Sifan Wang, Yujun Teng, Paris Perdikaris (2020) Understanding and mitigating gradient pathologies in physics-informed neural networks

  • Mohammad Amin Nabian, Rini Jasmine Gladstone, Hadi Meidani (2021) efficient training of physics-informed neural networks via importance sampling

Requirements

Libaries

cuda 10.2 # if gpu support is needed
python/3.6.5
gcc/5.5.0
openmpi/3.1.2

Python requirements

torch>=1.7.1 
h5py>=2.10.0
numpy>=1.19.0
Pillow>=7.2.0
matplotlib>=3.3.3
scipy>=1.6.1
pyDOE>=0.3.8

Usage of Interface

At the beginning you have to implement the datasets following the torch.utils.Dataset interface

from torch.utils.data import Dataset
sys.path.append(PATH_TO_PINN_FRAMEWORK)  # adding the pinn framework to your path
import PINNFramework as pf

class BoundaryConditionDataset(Dataset):

    def __init__(self, nb, lb, ub):
        """
        Constructor of the initial condition dataset
		"""
		
    def __getitem__(self, idx):
        """
        Returns data for initial state
        """
       

    def __len__(self):
        """
		Length of the dataset
        """


class InitialConditionDataset(Dataset):

    def __init__(self, **kwargs):
        """
        Constructor of the boundary condition dataset

        """


    def __len__(self):
        """
		Length of the dataset
        """
        

    def __getitem__(self, idx):
		"""
		Returns item at given index
		"""


class PDEDataset(Dataset):
    def __init__(self, nf, lb, ub):
        """
		Constructor of the PDE dataset
		"""
	
    def __len__(self):
        """
		Length of the dataset
        """
        

    def __getitem__(self, idx):
		"""
		Returns item at given index
		"""
		

In the main function you can create the loss-terms and the corresponding datasets. And define the pde function f which is the residual of the pde given residual points and model predictions u. For the boundary conditions: neumann, robin, dirchlet and periodic boundary condititions are supported.

if __name__ == main :

    # initial condition
    ic_dataset = InitialConditionDataset(...)
    initial_condition = pf.InitialCondition(dataset=ic_dataset)
    # boundary conditions
    bc_dataset = BoundaryConditionDataset(...)
    periodic_bc_u = pf.PeriodicBC(...)
    periodic_bc_v = pf.PeriodicBC(...)
    periodic_bc_u_x = pf.RobinBC(...)
    periodic_bc_v_x = pf.NeumannBC(...)
    # PDE 
	pde_dataset = PDEDataset(...)


    def f(x, u):
		"""
		
		Defines the residual of the pde f(x,u)=0
		
		"""


    pde_loss = pf.PDELoss(dataset=pde_dataset, func=f)

Finally you can create a model which is the surrogate for the PDE and create the PINN enviorment which helps you to train the surrogate.

model = pf.models.MLP(input_size=2, output_size=2, hidden_size=100, num_hidden=4) # creating a model. For example a mlp
pinn = pf.PINN(model, input_size=2, output_size=2 ,pde_loss = pde_loss, initial_condition=initial_condition, boundary_condition = [...], use_gpu=True)

pinn.fit(50000, 'Adam', 1e-3)

Deep HPM support

Instead of a PDE loss you can use a HPM model. The HPM model needs a function derivatives that calculates the needed derivatives, while the last returned derivative is the time_derivative. You can use the HPM loss a follows.

def derivatives(x,u):
	"""
	Returns the derivatives
	
	Args: 
		x (torch.Tensor) : residual points
		u (torch.Tensor) : predictions of the pde model
	"""
	pass
	
hpm_loss = pf.HPMLoss(pde_dataset,derivatives,hpm_model)
#HPM has no boundary conditions in general
pinn = pf.PINN(model, input_size=2, output_size=2 ,pde_loss = hpm_loss, initial_condition=initial_condition, boundary_condition = [], use_gpu=True)

Horovod Support

You can activate horovod support by setting the use_horovod flag in the constructor of the pinn

pinn = pf.PINN(model, input_size=2, output_size=2 ,pde_loss = pde_loss, initial_condition=initial_condition, boundary_condition = [...], use_gpu=True, use_horovod=True)
Keep in mind that the lbfgs-optimizer and the lbgfgs-finetuning is not supported with horovod activated. Another restriction is that the length or your dataset should not be smaller than the number of used GPUs for horovod.

Wandb support

Activate wandb-logging by creating an instance of a wandb logging. Its important that you have wandb installed. Look here for installing wandb: https://docs.wandb.ai/quickstart

logger = pf.WandbLogger(project, args) # create logger instance
pinn.fit(epochs=5000,logger=logger) # add logger to the fit method

Tensorboard support

Activate tensorboard-logging by creating an event file with tensorboardX. Its important that you have tensorboardX installed.

logger = pf.TensorBoardLogger(log_directory) # create logger instance
pinn.fit(epochs=5000,logger=logger) # add logger to the fit method

Developers

Scientific Supervision

Nico Hoffmann (HZDR)

Core Developers

Patrick Stiller (HZDR)
Maksim Zhdanov (HZDR)
Jeyhun Rustamov (HZDR)
Raj Dhansukhbhai Sutariya (HZDR)

neuralsolvers's People

Contributors

jeyhun1 avatar maxxxzdn avatar nih23 avatar psteinb avatar raj-sutariya avatar stillerpatrick avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

neuralsolvers's Issues

Model is not saved

PINN.py, line 109: torch.save(self.pinn_loss.model.state_dict(), hpm_path)
self.pinn_loss is a function

Tracking histogramms of loss terms

To keep track of gradient pathologies a tracking of the loss terms gradients is needed.
The logging should be done in the optimization process and can be activated by a separate flag in the fit function.

HPM-loss

Inherit from PDE Loss and implement the baviour of the HPM-loss

Provide a seperate pretraining function

At the moment, you need to set the number of main training epochs to 0, activate the pretaining function, and deactivate lbfgs fine-tuning. Here it would be better to have a separate function that trains initial condition only. This helps to find a suitable architecture.

benchmark suite

Implement benchmark suite with:

  • standard setups for various PDEs
  • default argument parser
  • switch of and on various PDEs by the argument list
  • logging
  • model saving depending on PDEs

Give all loss terms the attribute name

At the moment only the boundary condtion has the attribute name. For the workflow of the framework it would be more consistent if all loss terms have a name.

UserWarning in InitalCondition.py

https://github.com/ComputationalRadiationPhysics/NeuralSolvers/blob/2a9457257b35265d219db245eb765c6132559748/PINNFramework/InitalCondition.py#L28

/home/maxxxzdn/.local/lib/python3.8/site-packages/torch/nn/modules/loss.py:446: UserWarning: Using a target size (torch.Size([batch_size])) that is different to the input size (torch.Size([batch_size, 1])). This will likely lead to incorrect results due to broadcasting. Please ensure they have the same size.
return F.mse_loss(input, target, reduction=self.reduction)

Using prediction = model(x).reshape(-1) solves the problem

mlp.py

.to(device) implementation does not work properly. Needs to be changed to following:

self.lb = self.lb.to(device)
self.ub = self.ub.to(device)

Adding an opportunity too add model specific losses

Models like the GatedPINN uses a model specific loss in order to balance the utilization of the experts.
An option would be to give the model an attribute called loss.

In the PINN loss we can call the loss function with :

if hasattr(self.model, 'loss'):
    pinn_loss = pinn_loss + model.loss

Extend the PINN function to accept only one boundary condition

the function PINNFramewrok.PINN(.., boundary_condition,...) only accepts as input argument for boundary_condition elements of the form boundary_condition= [bc1,bc2,.. ], but even for only one bc it requires the input to be [bc]. Otherwise it raises 'KeyError' because it cannot call the bc from its name without the list form.

Modularize fit function

Currently, the fit function is a very big function that includes tracking, fitting, parallelization, etc.
Here we should modularize the functionalities to get a more maintainable code.

HPM-Loss

Inherit from PDE Loss and implement the baviour of the HPM-loss

Making logging more consistent

At the moment the logging is not very consistent. The weighted loss is uploaded to the logger one step earlier than the scalars. That should be changed by a consistent set of the epoch in the logger call:

for key, value in self.loss_log.items():
    logger.log_scalar(scalar=value / batch_counter, name=key, epoch=epoch+1)

vs:

logger.log_scalar(scalar=pinn_loss_sum / batch_counter, name=" Weighted PINN Loss", epoch=epoch)

Rework readme

The general idea of the framework is not well transported and should be better illustrated

Weighting is not set correctly

In the HPMLoss the weighting is not set correctly.

super(HPMLoss, self).__init__(dataset, None, name, norm='L2', weight=1.)

should be

super(HPMLoss, self).__init__(dataset, None, name, norm='L2', weight=weight)

The for loops for pretraining and main training are ignored

when choosing extremely small no. of samples , which lead that the len(no._of batches) of the dataset which is fed to the dataloader to be equal to zero, which makes the iteration loop to for i in range( 0,0, step): .. thats why the looping didn't work and the ic_loss wasn't calculated at the first place.
i would suggest creating a warning message when choosing a no. of samples which can make the length of the datasets yields to zero after the using of "//" operator.

the for loops are found in line 503 and 518 in the pinn.fit () function in the pinn.py file

Time Measurement

At the moment there is no measurement of elapsed time per epoch and complete training time. That should be added soon.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.