Skip to content

Commit

Permalink
Merge pull request PaddlePaddle#150 from Liu-xiandong/model_standardi…
Browse files Browse the repository at this point in the history
…zation

Model standardization.
  • Loading branch information
Liu-xiandong authored Aug 3, 2022
2 parents 47fa168 + e2a0d6a commit c45b4fb
Show file tree
Hide file tree
Showing 7 changed files with 320 additions and 9 deletions.
59 changes: 51 additions & 8 deletions examples/laplace/laplace2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,43 @@
import numpy as np
import paddle

paddle.seed(1)
np.random.seed(1)
cfg = psci.utils.parse_args()

if cfg is not None:
# Geometry
npoints = cfg['Geometry']['npoints']
seed_num = cfg['Geometry']['seed']
sampler_method = cfg['Geometry']['sampler_method']
# Network
epochs = cfg['Global']['epochs']
num_layers = cfg['Model']['num_layers']
hidden_size = cfg['Model']['hidden_size']
activation = cfg['Model']['activation']
# Optimizer
learning_rate = cfg['Optimizer']['lr']['learning_rate']
# Post-processing
solution_filename = cfg['Post-processing']['solution_filename']
vtk_filename = cfg['Post-processing']['vtk_filename']
checkpoint_path = cfg['Post-processing']['checkpoint_path']
else:
# Geometry
npoints = 10201
seed_num = 1
sampler_method = 'uniform'
# Network
epochs = 20000
num_layers = 5
hidden_size = 20
activation = 'tanh'
# Optimizer
learning_rate = 0.001
# Post-processing
solution_filename = 'output_laplace2d'
vtk_filename = 'output_laplace2d'
checkpoint_path = 'checkpoints'

paddle.seed(seed_num)
np.random.seed(seed_num)

# analytical solution
ref_sol = lambda x, y: np.cos(x) * np.cosh(y)
Expand All @@ -29,8 +64,7 @@
criteria=lambda x, y: (y == 1.0) | (y == 0.0) | (x == 0.0) | (x == 1.0))

# discretize geometry
npoints = 10201
geo_disc = geo.discretize(npoints=npoints, method="uniform")
geo_disc = geo.discretize(npoints=npoints, method=sampler_method)

# Laplace
pde = psci.pde.Laplace(dim=2)
Expand All @@ -47,7 +81,11 @@
# Network
# TODO: remove num_ins and num_outs
net = psci.network.FCNet(
num_ins=2, num_outs=1, num_layers=5, hidden_size=20, activation='tanh')
num_ins=2,
num_outs=1,
num_layers=num_layers,
hidden_size=hidden_size,
activation=activation)

# Loss
loss = psci.loss.L2()
Expand All @@ -56,13 +94,18 @@
algo = psci.algorithm.PINNs(net=net, loss=loss)

# Optimizer
opt = psci.optimizer.Adam(learning_rate=0.001, parameters=net.parameters())
opt = psci.optimizer.Adam(
learning_rate=learning_rate, parameters=net.parameters())

# Solver
solver = psci.solver.Solver(pde=pde_disc, algo=algo, opt=opt)
solution = solver.solve(num_epoch=25, checkpoint_freq=20)
solution = solver.solve(num_epoch=epochs)

psci.visu.save_vtk(geo_disc=pde_disc.geometry, data=solution)
psci.visu.save_vtk(
filename=vtk_filename, geo_disc=pde_disc.geometry, data=solution)

psci.visu.save_npy(
filename=solution_filename, geo_disc=pde_disc.geometry, data=solution)

# MSE
# TODO: solution array to dict: interior, bc
Expand Down
1 change: 1 addition & 0 deletions paddlescience/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@
from . import solver
from . import visu
from . import data
from . import utils

config.try_enable_cinn()
6 changes: 6 additions & 0 deletions paddlescience/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,17 @@ def get_dtype():


def enable_visualdl():
"""
Use visualdl.
"""
global _use_visualdl
_use_visualdl = True


def visualdl_enabled():
'''
Determine whether visualdl is enabled.
'''
return _use_visualdl


Expand Down
167 changes: 167 additions & 0 deletions paddlescience/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserve.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import yaml
import argparse
from .config import enable_visualdl, enable_static, enable_prim

__all__ = ['parse_args']


class AttrDict(dict):
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(key)

def __setattr__(self, key, value):
if key in self.__dict__:
self.__dict__[key] = value
else:
self[key] = value


def create_attr_dict(yaml_config):
from ast import literal_eval
for key, value in yaml_config.items():
if type(value) is dict:
yaml_config[key] = value = AttrDict(value)
if isinstance(value, str):
try:
value = literal_eval(value)
except BaseException:
pass
if isinstance(value, AttrDict):
create_attr_dict(yaml_config[key])
else:
yaml_config[key] = value


def parse_config(cfg_file, config_index):
"""Load a config file into AttrDict"""
with open(cfg_file, 'r') as fopen:
yaml_config = yaml.load(fopen, Loader=yaml.SafeLoader)
create_attr_dict(yaml_config[config_index])
return yaml_config[config_index]


def override(dl, ks, v):
"""
Recursively replace dict of list
Args:
dl(dict or list): dict or list to be replaced
ks(list): list of keys
v(str): value to be replaced
"""

def str2num(v):
try:
return eval(v)
except Exception:
return v

assert isinstance(dl, (list, dict)), ("{} should be a list or a dict")
assert len(ks) > 0, ('lenght of keys should larger than 0')
if isinstance(dl, list):
k = str2num(ks[0])
if len(ks) == 1:
assert k < len(dl), ('index({}) out of range({})'.format(k, dl))
dl[k] = str2num(v)
else:
override(dl[k], ks[1:], v)
else:
if len(ks) == 1:
assert ks[0] in dl, ('{} is not exist in {}'.format(ks[0], dl))
dl[ks[0]] = str2num(v)
else:
override(dl[ks[0]], ks[1:], v)


def override_config(config, options=None):
"""
Recursively override the config
Args:
config(dict): dict to be replaced
options(list): list of pairs(key0.key1.idx.key2=value)
such as: [
'topk=2',
'VALID.transforms.1.ResizeImage.resize_short=300'
]
Returns:
config(dict): replaced config
"""
if options is not None:
for opt in options:
assert isinstance(opt,
str), ("option({}) should be a str".format(opt))
assert "=" in opt, (
"option({}) should contain a ="
"to distinguish between key and value".format(opt))
pair = opt.split('=')
assert len(pair) == 2, ("there can be only a = in the option")
key, value = pair
keys = key.split('.')
override(config, keys, value)

return config


def get_config(fname, config_index=0, overrides=None):
"""
Read config from file
"""
if fname is None and overrides is None:
return None
assert os.path.exists(fname), (
'config file({}) is not exist'.format(fname))
config = parse_config(fname, config_index)
override_config(config, overrides)

return config


def parse_args():
parser = argparse.ArgumentParser(description='PaddleScience')
parser.add_argument(
'-c', '--config-file', metavar="FILE", help='config file path')

parser.add_argument(
'-i',
'--config-index',
type=int,
default=0,
help='run validation every interval')

# config options
parser.add_argument(
"-o", "--opt", nargs='+', help="set configuration options")

args = parser.parse_args()

# Get config
cfg = get_config(args.config_file, args.config_index, args.opt)

if cfg is not None:
# Enable related flags
if cfg['Global']['use_visualdl'] == True:
enable_visualdl()
if cfg['Global']['static_enable'] == True:
enable_static()
if cfg['Global']['prim_enable'] == True:
enable_prim()
else:
pass

return cfg
2 changes: 1 addition & 1 deletion paddlescience/visu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from .visu_vtk import save_vtk
from .visu_vtk import save_vtk, save_npy
from .visu_vtk import __save_vtk_raw
from .visu_matplotlib import save_mpl, plot_mpl
52 changes: 52 additions & 0 deletions paddlescience/visu/visu_vtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,58 @@
from .. import config


# Save geometry pointwise of numpy
def save_npy(filename="output", time_array=None, geo_disc=None, data=None):
"""
Save data to numpy format.
Parameters:
filename(string): file name.
time_array(list or numpy array, optional): time steps list / array.
geo_disc (GeometryDiscrete): discrete geometry.
data (numpy array, optional): data to be saved.
Example:
>>> import paddlescience as psci
>>> psci.visu.save_npy(geo_disc=pde_disc.geometry, data=solution)
"""
nt = 1 if (time_array is None) else len(time_array) - 1
nprocs = paddle.distributed.get_world_size()
nrank = paddle.distributed.get_rank()
if nprocs == 1:
geo_disc_sub = geo_disc
else:
geo_disc_sub = geo_disc.sub(nprocs, nrank)

# concatenate data and cordiante
points_vtk = __concatenate_geo(geo_disc_sub)

# points's shape is [ndims][npoints]
npoints = len(points_vtk[0])
ndims = len(points_vtk)

# data
if data is None:
data_vtk = {"placeholder": np.ones(npoints, dtype=config._dtype)}
elif type(data) == types.LambdaType:
data_vtk = dict()
if ndims == 3:
data_vtk["data"] = data(points_vtk[0], points_vtk[1],
points_vtk[2])
elif ndims == 2:
data_vtk["data"] = data(points_vtk[0], points_vtk[1])
else:
data_vtk = __concatenate_data(data, nt)

for t in range(nt):
fpname = filename + "-t" + str(t + 1) + "-p" + str(nrank)
current_cord = np.array(points_vtk).astype(config._dtype)
current_data = np.array(list(data_vtk[t].values()))
result = np.concatenate((current_cord, current_data), axis=0).T
np.save(fpname, result)


# Save geometry pointwise
def save_vtk(filename="output", time_array=None, geo_disc=None, data=None):
"""
Expand Down
42 changes: 42 additions & 0 deletions tests/config/laplace2d.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
- input: 0
Global:
use_visualdl: False
static_enable: False
prim_enable: False
epochs: 20000
Geometry:
npoints: 512
seed: 1
sampler_method: 'sampling'
Model:
num_layers: 5
hidden_size: 20
activation: 'tanh'
Optimizer:
lr:
learning_rate: 0.001
Post-processing:
solution_filename: 'output_laplace2d'
vtk_filename: 'output_laplace2d'
checkpoint_path: 'checkpoints'
- input: 1
Global:
use_visualdl: False
static_enable: False
prim_enable: False
epochs: 20000
Geometry:
npoints: 258
seed: 1
sampler_method: 'sampling'
Model:
num_layers: 5
hidden_size: 20
activation: 'tanh'
Optimizer:
lr:
learning_rate: 0.001
Post-processing:
solution_filename: 'output_laplace2d'
vtk_filename: 'output_laplace2d'
checkpoint_path: 'checkpoints'

0 comments on commit c45b4fb

Please sign in to comment.