diff --git a/prepare_data.py b/prepare_data.py new file mode 100644 index 0000000..f9d89fb --- /dev/null +++ b/prepare_data.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +import reacdiff.parsing as parsing +import reacdiff.data.preprocess as preprocess + + +if __name__ == '__main__': + args = parsing.parse_dataprep_args() + preprocess.preprocess(args.data_path) diff --git a/reacdiff/data/data.py b/reacdiff/data/data.py index b8bbdbe..925d0d2 100644 --- a/reacdiff/data/data.py +++ b/reacdiff/data/data.py @@ -1,3 +1,4 @@ +import h5py import numpy as np import reacdiff.utils as utils @@ -49,16 +50,21 @@ def __getitem__(self, item): return Dataset(self.data[item], self.targets[item], self.data2[item]) -def load_data(path, targets=False): - if targets: - return np.random.rand(100, 26) - data = np.random.rand(100, 50, 128, 128) - data = np.expand_dims(data, axis=-1) +def load_data(path, max_read=None, key='data'): + """ + :param path: An HDF5 file. + :param max_read: Maximum number of samples to read. + :param key: Data key in HDF5 file. + :return: Numpy array of data + """ + with h5py.File(path, 'r') as f: + data = f[key][:] if max_read is None else f[key][:max_read] return data -def save_data(data, path): - raise NotImplementedError +def save_data(data, path, key='data'): + with h5py.File(path, 'w') as f: + f.create_dataset(key, data=data) def split_data(data, splits=(0.9, 0.05, 0.05), seed=None): diff --git a/reacdiff/data/preprocess.py b/reacdiff/data/preprocess.py new file mode 100644 index 0000000..635d60f --- /dev/null +++ b/reacdiff/data/preprocess.py @@ -0,0 +1,34 @@ +import os + +import h5py +import numpy as np + +import reacdiff.data.data as datamod + + +def preprocess(path): + """ + :param path: An HDF5 file. + """ + f = h5py.File(path, 'r') + targets = f['A1'] + states = f['y'] + + assert len(targets.shape) == 2 + assert len(states.shape) == 5 + assert states.shape[0] == 2 + + targets = targets[:] + states = states[:] + targets = np.swapaxes(targets, 0, 1) + states = np.transpose(states, (0, 4, 1, 2, 3)) + data, data2 = np.expand_dims(states, axis=-1) + + name = os.path.splitext(path)[0] + targets_path = name + '_targets.h5' + data_path = name + '_states.h5' + data_path2 = name + '_states2.h5' + + datamod.save_data(targets, targets_path) + datamod.save_data(data, data_path) + datamod.save_data(data2, data_path2) diff --git a/reacdiff/parsing.py b/reacdiff/parsing.py new file mode 100644 index 0000000..7e53d47 --- /dev/null +++ b/reacdiff/parsing.py @@ -0,0 +1,89 @@ +import argparse +import os + + +def parse_dataprep_args(): + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + parser.add_argument('--data_path', type=str, required=True, + help='Path to HDF5 data file') + return parser.parse_args() + + +def parse_train_args(): + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + # General arguments + parser.add_argument('--data_path', type=str, required=True, + help='Path to data containing observable states') + parser.add_argument('--targets_path', type=str, required=True, + help='Path to targets') + parser.add_argument('--data_path2', type=str, + help='Path to data containing additional observable states') + parser.add_argument('--save_dir', type=str, default=os.getcwd(), + help='Directory where model checkpoints will be saved') + parser.add_argument('--splits', type=float, nargs=3, default=[0.9, 0.05, 0.05], + help='Split proportions for train/validation/test sets') + parser.add_argument('--save_test_data', action='store_true', + help='Save test data and targets to file') + parser.add_argument('--test_data_path', type=str, + help='Path to separate test data') + parser.add_argument('--test_targets_path', type=str, + help='Path to separate test targets') + parser.add_argument('--test_data_path2', type=str, + help='Path to separate test data for additional observable') + parser.add_argument('--quiet', action='store_true', + help='Do not print model details and batch information during training') + parser.add_argument('--cpu', action='store_true', + help='Run on CPU instead of GPU') + parser.add_argument('--seed', type=int, default=7, + help='Random seed for reproducibility') + + # Training arguments + parser.add_argument('--batch_size', type=int, default=32, + help='Batch size') + parser.add_argument('--epochs', type=int, default=30, + help='Maximum number of epochs to run') + parser.add_argument('--lr_start', type=float, default=1e-3, + help='Initial learning rate') + parser.add_argument('--lr_end', type=float, default=1e-4, + help='Final learning rate') + parser.add_argument('--patience', type=int, default=5, + help='Number of epochs without improvement after which training will be stopped') + parser.add_argument('--max_norm', type=float, default=2.0, + help='Maximum gradient norm before clipping occurs') + + # Encoder arguments + parser.add_argument('--feat_maps', type=int, default=16, + help='Number of feature maps in first convolutional layer') + parser.add_argument('--first_conv_size', type=int, default=7, + help='Filter size in first convolutional layer') + parser.add_argument('--first_conv_stride', type=int, default=2, + help='Strides in first convolutional layer') + parser.add_argument('--first_pool_size', type=int, default=3, + help='Window size in first pool') + parser.add_argument('--first_pool_stride', type=int, default=2, + help='Strides in first pool') + parser.add_argument('--growth_rate', type=int, default=12, + help='Growth rate in dense blocks') + parser.add_argument('--blocks', type=int, nargs='+', default=[3, 4, 5], + help='Numbers of layers in each dense block') + parser.add_argument('--dropout', type=float, default=0.0, + help='Dropout rate after convolutions') + parser.add_argument('--reduction', type=float, default=0.5, + help='Compression rate in transition blocks') + parser.add_argument('--no_bottleneck', action='store_true', + help='Do not use bottleneck convolution in dense blocks') + parser.add_argument('--flatten_last', action='store_true', + help='Flatten instead of global pool before output') + + # RNN arguments + parser.add_argument('--rnn_layers', type=int, default=1, + help='Number of RNN layers') + parser.add_argument('--rnn_units', type=int, default=100, + help='Number of units in RNN') + + return parser.parse_args() diff --git a/reacdiff/train/__init__.py b/reacdiff/train/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/reacdiff/train/run_training.py b/reacdiff/train/run_training.py new file mode 100644 index 0000000..38864ff --- /dev/null +++ b/reacdiff/train/run_training.py @@ -0,0 +1,77 @@ +import os + +import reacdiff.data.data as datamod +import reacdiff.models.crnn as models +import reacdiff.train.train as train + + +def run_training(args): + # Load data + print('Loading data') + data = datamod.Dataset( + datamod.load_data(args.data_path), + datamod.load_data(args.targets_path), + None if args.data_path2 is None else datamod.load_data(args.data_path2) + ) + + # Split data + print(f'Splitting data with seed {args.seed}') + train_data, val_data, test_data = datamod.split_data(data, splits=args.splits, seed=args.seed) + + if args.test_data_path is not None and args.test_targets_path is not None: + test_data = datamod.Dataset( + datamod.load_data(args.test_data_path), + datamod.load_data(args.test_targets_path), + None if args.test_data_path2 is None else datamod.load_data(args.test_data_path2) + ) + + os.makedirs(args.save_dir, exist_ok=True) + + if args.save_test_data: + test_data.save(os.path.join(args.save_dir, 'test')) + + print(f'Train size = {len(train_data):,} | val size = {len(val_data):,} | test size = {len(test_data):,}') + + # Build model + crnn = models.CRNN( + time_steps=train_data.data.shape[1], + input_shape=train_data.data.shape[2:], + output_dim=train_data.targets.shape[1], + observables=train_data.get_num_observables(), + rnn_layers=args.rnn_layers, + rnn_units=args.rnn_units, + use_gpu=not args.cpu + ) + crnn.build( + feat_maps=args.feat_maps, + first_conv_size=args.first_conv_size, + first_conv_stride=args.first_conv_stride, + first_pool_size=args.first_pool_size, + first_pool_stride=args.first_pool_stride, + growth_rate=args.growth_rate, + blocks=args.blocks, + dropout=args.dropout, + reduction=args.reduction, + bottleneck=not args.no_bottleneck, + flatten_last=args.flatten_last + ) + + model_dir = os.path.join(args.save_dir, 'model') + os.makedirs(model_dir, exist_ok=True) + + # Train model + train.train(crnn, train_data, model_dir, + batch_size=args.batch_size, + epochs=args.epochs, + val_data=val_data, + patience=args.patience, + lr_start=args.lr_start, + lr_end=args.lr_end, + max_norm=args.max_norm, + quiet=args.quiet) + + # Evaluate on test set + print('Evaluating test data') + metrics = crnn.model.evaluate(test_data.get_data(), test_data.targets, + batch_size=args.batch_size) + print(*(f'{name}: {metric:.4f}' for name, metric in zip(crnn.model.metrics_names, metrics)), sep='; ') diff --git a/reacdiff/train/train.py b/reacdiff/train/train.py new file mode 100644 index 0000000..aa7c8ff --- /dev/null +++ b/reacdiff/train/train.py @@ -0,0 +1,59 @@ +import os + +import keras + +import reacdiff.utils as utils + + +def train(crnn, data, save_dir, + batch_size=32, + epochs=30, + val_data=None, + patience=5, + lr_start=1e-3, + lr_end=1e-4, + max_norm=2.0, + quiet=False): + """ + :param crnn: CRNN instance. + :param data: Training data. + :param save_dir: directory to save models to. + :param batch_size: int, batch size. + :param epochs: maximum number of epochs. + :param val_data: Validation data. + :param patience: patience. + :param lr_start: float, initial learning rate. + :param lr_end: float, final learning rate. + :param max_norm: float, maximum gradient norm. + :param quiet: bool, print less information + """ + optimizer = keras.optimizers.Adam(lr=lr_start, clipnorm=max_norm) + crnn.model.compile(optimizer=optimizer, loss='mse', metrics=[utils.rmse, utils.mae]) + if not quiet: + crnn.encoder.summary() + crnn.rnn.summary() + crnn.model.summary() + + model_name = 'model.{epoch:03d}.h5' + model_path = os.path.join(save_dir, model_name) + + def lr_schedule(epoch, _): + return lr_start * ((lr_end / lr_start) ** (epoch / epochs)) + + checkpoint = keras.callbacks.ModelCheckpoint(filepath=model_path, + verbose=1, + save_best_only=True) + early_stopping = keras.callbacks.EarlyStopping(patience=patience, + verbose=1, + restore_best_weights=True) + lr_scheduler = keras.callbacks.LearningRateScheduler(lr_schedule, + verbose=1) + callbacks = [checkpoint, early_stopping, lr_scheduler] + + crnn.model.fit(data.get_data(), data.targets, + batch_size=batch_size, + epochs=epochs, + validation_data=(val_data.get_data(), val_data.targets), + shuffle=True, + verbose=2 if quiet else 1, + callbacks=callbacks) diff --git a/solver/DDFT.m b/solver/DDFT.m new file mode 100644 index 0000000..496c57a --- /dev/null +++ b/solver/DDFT.m @@ -0,0 +1,51 @@ +%parameter search +L = [5,5]*2; +N = [256,256]*2; +n = prod(N); +n0 = 0.07; +sigma = 0.01; + +rng(1); +n0 = n0 + sigma*randn(N); +y0 = fftn(n0); +y0 = y0(:); +% y00 = y0(1); +% y0(1) = []; + +% %use image? +% im = imread('cameraman.tif'); +% im = imresize(im,N); +% C2 = fft(im); +% C2 = C2(:); +% C2(1) = 0; +% C2 = C2/max(abs(C2))/1.5; + +[k2,k] = formk(N,L); +k2 = k2(:); +% k2(1) = []; + +kind1 = k{1}; kind2 = k{2}; +[kind1,kind2] = ndgrid(kind1(:),kind2(:)); +theta = angle(kind1+i*kind2); + +theta = theta(:); + +k0 = 10; +alpha = 2; +C2 = exp(-(sqrt(k2)-k0).^2/(2*alpha^2)); +C22 = C2; +% C22 = C2 .* (1+cos(theta))/2; +% C22 = C2 .* (exp(-(theta-pi/2).^2/(2*(50/180*pi)^2))+exp(-(theta+pi/2).^2/(2*(50/180*pi)^2)))/2; +J = -k2.*(-C22); + +tspan = linspace(0,0.14,100); +tspan = [0,1.7]; +tspan = linspace(0,1.07,100); +% tspan = [0,0.14]; +options = odeset('AbsTol',1e-3); +[tout,yout] = odeimex(@(t,y) DDFT_nlin(t,y,k2,N),J,tspan,y0); +% Nt = 10000; +% h = (tspan(end)-tspan(1))/Nt; +% [tout,yout] = odeimexez(@(t,y) DDFT_nlin(t,y,k2,N),J,h,Nt,y0,[],1:100:Nt); + +figure; k2real(yout(:,end),N); diff --git a/solver/DDFT_nlin.m b/solver/DDFT_nlin.m new file mode 100644 index 0000000..53cf4b4 --- /dev/null +++ b/solver/DDFT_nlin.m @@ -0,0 +1,17 @@ +function dy = DDFT_nlin(t,y,k2,N,y00) + if nargin > 4 && ~isempty(y00) + %k=0 component is omitted + k0flag = true; + y = [y00;y(:)]; + else + k0flag = false; + end + y = real(ifftn(reshape(y,N))); + % mu = y - y.^2/2 + y.^3/3; + mu = log(1+y); + fmu = reshape(fftn(mu,N),[],1); + if k0flag + fmu(1) = []; + end + dy = -k2 .* fmu; +end diff --git a/solver/DDFT_nucleation.m b/solver/DDFT_nucleation.m new file mode 100644 index 0000000..2849b62 --- /dev/null +++ b/solver/DDFT_nucleation.m @@ -0,0 +1,49 @@ +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +range = [1.5,3.5]; +thickness = 0.1; +roi = roi_rectangle(xx,yy,range,range,thickness); +center = L/2; +radius = 0.18*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +rho = (sum(y0) - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; +figure; imagesc(reshape(y0,N)); + +tspan2 = linspace(0,0.4,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +figure; visualize([],[],[],y2(1:10:end,:),'c',false,'ImageSize',N); + +ind = 1:5:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +% x_opt = IP_DDFT(tdata,ydata,params,[21,21],'k'); %this stagnates at iter 17 after 63 func counts + +% x_opt = IP_DDFT(tdata,ydata,params,[61,61],'real'); + +options = optimoptions('fminunc','HessianFcn','objective','Algorithm','trust-region'); +x_opt = IP_DDFT(tdata,ydata,params,10,'isotropic',options); + +% ind = 10:3:61; +% tdata = t1(ind); +% ydata = y1(ind,:); +% x_opt = IP_DDFT(tdata,ydata,params,[21,21],'k'); %this stagnates at iter 1 after 37 func counts diff --git a/solver/DDFT_nucleation11.m b/solver/DDFT_nucleation11.m new file mode 100644 index 0000000..82c176a --- /dev/null +++ b/solver/DDFT_nucleation11.m @@ -0,0 +1,55 @@ +%data from DDFT_nucleation3 +%use PFC to fit, fit C and mu +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,1.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 10:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation11.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +x_guess = [0,-10,2,0,-3]; +x_guess = [0,-10,0.5,0,-3]; %11 +[x_opt,~,exitflag] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3); diff --git a/solver/DDFT_nucleation12.m b/solver/DDFT_nucleation12.m new file mode 100644 index 0000000..00ddbeb --- /dev/null +++ b/solver/DDFT_nucleation12.m @@ -0,0 +1,55 @@ +%data from DDFT_nucleation3 +%based on DDFT_nucleation11, with a different initial guess (same for C as DDFT_nucleation7) +addpath('../../CHACR/GIP') +addpath('../../CHACR'); +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,1.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 10:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation12.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +x_guess = [0,-5,0.5,0,-3]; +[x_opt,~,exitflag] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3); diff --git a/solver/DDFT_nucleation13.m b/solver/DDFT_nucleation13.m new file mode 100644 index 0000000..7e625a4 --- /dev/null +++ b/solver/DDFT_nucleation13.m @@ -0,0 +1,65 @@ +%based on DDFT_nucleation11 +%use a different time range +addpath('../../CHACR/GIP') +runoptim = false; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation13.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +if runoptim + x_guess = [0,-10,0.5,0,-3]; + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'tspan',300); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + modelfunc.mu = @(x) x - x.^2/2 + x.^3/3; + arg.C = linspace(0,2,500); + arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); + frameindex = 1:20:100; + history_production(resultpath,[1,21,45,125],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'FrameIndex',frameindex,'IP_DDFT_arg',{'Nmu',3},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',[min(ydata(:)),2]); + f = gcf; + f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation14.m b/solver/DDFT_nucleation14.m new file mode 100644 index 0000000..bfd34b3 --- /dev/null +++ b/solver/DDFT_nucleation14.m @@ -0,0 +1,64 @@ +%based on DDFT_nucleation11 +%same time range as 13, use up to 8th order PFC +%fail +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +kernelSize = 3; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation14.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +%x_guess = [0,0,-20,0.5,0,-3] + +varload = load([largedatapath,'DDFT_nucleation11']); +x_opt = varload.history(end,:); +x_opt(2) = -exp(x_opt(2)); +x_guess = [x_opt(1:2),-30,x_opt(3:5)]; +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'tspan',300); + +% varload = load([largedatapath,'DDFT_nucleation11']); +% x_opt = varload.history(end,:); +% ypred = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],x_opt,'Nmu',3,'eval',true); diff --git a/solver/DDFT_nucleation15.m b/solver/DDFT_nucleation15.m new file mode 100644 index 0000000..15a10a3 --- /dev/null +++ b/solver/DDFT_nucleation15.m @@ -0,0 +1,65 @@ +%based on DDFT_nucleation11 +%same time range as 13, a different initial guess +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation15.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [0,-12,0.5,0,-3]; + + + + + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'tspan',300); + + + +% ypred = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],x_opt,'Nmu',3,'eval',true); diff --git a/solver/DDFT_nucleation16.m b/solver/DDFT_nucleation16.m new file mode 100644 index 0000000..11b8b0e --- /dev/null +++ b/solver/DDFT_nucleation16.m @@ -0,0 +1,65 @@ +%based on DDFT_nucleation11 +%same time range as 13, a different initial guess +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation15.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +x_guess = [0,-12,0.5,0,-3]; + + + + + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'tspan',300); + + + +% ypred = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],x_opt,'Nmu',3,'eval',true); diff --git a/solver/DDFT_nucleation17.m b/solver/DDFT_nucleation17.m new file mode 100644 index 0000000..3dd54b0 --- /dev/null +++ b/solver/DDFT_nucleation17.m @@ -0,0 +1,63 @@ +%based on DDFT_nucleation11 +%same time range as 15, a different initial guess +%optimize D as well +%fail, no need to optimize D together +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation17.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [0,-12,0.5,0,-3,log(0.1)]; + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'D',true,'tspan',300); + + + +% ypred = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],x_opt,'Nmu',3,'eval',true); diff --git a/solver/DDFT_nucleation18.m b/solver/DDFT_nucleation18.m new file mode 100644 index 0000000..9dc56bf --- /dev/null +++ b/solver/DDFT_nucleation18.m @@ -0,0 +1,63 @@ +%based on DDFT_nucleation11 +%same time range as 15, easy initial guess +%optimize D as well +%fail, no need to optimize D together +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation18.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [0,-10,0.5,0,-3,log(0.1)]; + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'D',true,'tspan',300); + + + +% ypred = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],x_opt,'Nmu',3,'eval',true); diff --git a/solver/DDFT_nucleation19.m b/solver/DDFT_nucleation19.m new file mode 100644 index 0000000..7ba5209 --- /dev/null +++ b/solver/DDFT_nucleation19.m @@ -0,0 +1,61 @@ +%based on DDFT_nucleation13 +%with discrete number of points +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation19.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [0,-10,0.5,0,-3]; + + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',false); + + +% ypred = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],x_opt,'Nmu',3,'eval',true); diff --git a/solver/DDFT_nucleation2.m b/solver/DDFT_nucleation2.m new file mode 100644 index 0000000..b25dbf6 --- /dev/null +++ b/solver/DDFT_nucleation2.m @@ -0,0 +1,65 @@ +addpath('../../CHACR/GIP') +runoptim = false; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +if ~exist('tdata','var') + [t1,y1,params] = solver_DDFT([],[],params); + + xx = linspace(0,L(1),N(1)); + yy = linspace(0,L(2),N(2)); + [xx,yy] = ndgrid(xx,yy); + range = [1.5,3.5]; + thickness = 0.1; + roi = roi_rectangle(xx,yy,range,range,thickness); + center = L/2; + radius = 0.06*L(1); + thickness = 0.01*L(1); + roi = roi_circle(xx,yy,center,radius,thickness); + + %nucleus + y0 = y1(end,:)'; + roi = roi(:); + rho = (sum(y0) - sum(roi.*y0)) / sum(1-roi); + y0 = roi.*y0 + (1-roi)*rho; + figure; imagesc(reshape(y0,N)); + + tspan2 = linspace(0,1.05,100); + tspan2 = linspace(0,1.5,100); + [t2,y2] = solver_DDFT(tspan2,y0,params); + + figure; visualize([],[],[],y2(1:10:end,:),'c',false,'ImageSize',N); + + ind = 20:2:100; + tdata = t2(ind); + ydata = y2(ind,:); + toc +end + +kernelSize = [21,21]; +Cspace = 'k'; + +resultpath = [largedatapath,'DDFT_nucleation2.mat']; +if runoptim + save_history = true; + options = optimoptions('fminunc'); + if save_history + options = optimoptions(options,'OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); + end + + x_opt = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_opt); + % [val,gradient] = IP_DDFT_debug(x_opt/max(x_opt)*1.2,tdata,ydata,params,[21,21],'k'); +else + meta.C.index = floor((prod(kernelSize)+1)/2); + meta.C.exp = false; + frameindex = [1,6,12,23,41]; + history_production(resultpath,[1,2,11,71,171],[],[],meta,tdata-tdata(1),ydata,params,kernelSize,Cspace,'FrameIndex',frameindex,'CtruthSubplot',[2,length(frameindex)]); + f = gcf; + f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation20.m b/solver/DDFT_nucleation20.m new file mode 100644 index 0000000..5ceba00 --- /dev/null +++ b/solver/DDFT_nucleation20.m @@ -0,0 +1,58 @@ +%based on DDFT_nucleation13 +%with discrete number of points +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:10:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation20.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000,'FunctionTolerance',1e-7); + +x_guess = [0,-11,0.5,0,-3]; + + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true); diff --git a/solver/DDFT_nucleation21.m b/solver/DDFT_nucleation21.m new file mode 100644 index 0000000..ba0716d --- /dev/null +++ b/solver/DDFT_nucleation21.m @@ -0,0 +1,70 @@ +%based on DDFT_nucleation13 +%with discrete number of points +addpath('../../CHACR/GIP') +runoptim = false; + +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; +params.dx = L./N; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +if ~exist('t2','var') + tic; + [t1,y1,params] = solver_DDFT([],[],params); + + xx = linspace(0,L(1),N(1)); + yy = linspace(0,L(2),N(2)); + [xx,yy] = ndgrid(xx,yy); + center = L/2; + radius = 0.06*L(1); + thickness = 0.01*L(1); + roi = roi_circle(xx,yy,center,radius,thickness); + + %nucleus + y0 = y1(end,:)'; + roi = roi(:); + y02 = 0.045; + rho = (y02*n - sum(roi.*y0)) / sum(1-roi); + y0 = roi.*y0 + (1-roi)*rho; + + tspan2 = linspace(0,2.5,100); + [t2,y2] = solver_DDFT(tspan2,y0,params); + toc +end + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); + + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation21.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000,'FunctionTolerance',1e-7); + + +if runoptim + x_guess = [0,-11,0.5,0,-3]; + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + modelfunc.mu = @(x) x - x.^2/2 + x.^3/3; + arg.C = linspace(0,2,500); + arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); + history_production(resultpath,[1,41,71,1667],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'IP_DDFT_arg',{'Nmu',3},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',[min(ydata(:)),2]); + f = gcf; + f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation22.m b/solver/DDFT_nucleation22.m new file mode 100644 index 0000000..59fbf60 --- /dev/null +++ b/solver/DDFT_nucleation22.m @@ -0,0 +1,59 @@ +%based on DDFT_nucleation21 +%different initial condition +%with discrete number of points +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation22']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000,'FunctionTolerance',1e-7); + +x_guess = [0,-8,0.5,0,-3]; + + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true); diff --git a/solver/DDFT_nucleation23.m b/solver/DDFT_nucleation23.m new file mode 100644 index 0000000..888db4d --- /dev/null +++ b/solver/DDFT_nucleation23.m @@ -0,0 +1,67 @@ +%based on DDFT_nucleation21 +%different initial condition +%with discrete number of points +addpath('../../CHACR/GIP') +runoptim = false; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation23']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000,'FunctionTolerance',1e-7); + +if runoptim + x_guess = [0,-9,0.5,0,-3]; + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + modelfunc.mu = @(x) x - x.^2/2 + x.^3/3; + arg.C = linspace(0,2,500); + arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); + history_production(resultpath,[1,21,38,1797],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'IP_DDFT_arg',{'Nmu',3},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',[min(ydata(:)),2]); + f = gcf; + f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation24.m b/solver/DDFT_nucleation24.m new file mode 100644 index 0000000..c103a60 --- /dev/null +++ b/solver/DDFT_nucleation24.m @@ -0,0 +1,53 @@ +%based on DDFT_nucleation13 +%use isotropic_cutoff +addpath('../../CHACR/GIP') +runoptim = true; + +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; +params.dx = L./N; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +if ~exist('t2','var') + tic; + [t1,y1,params] = solver_DDFT([],[],params); + + xx = linspace(0,L(1),N(1)); + yy = linspace(0,L(2),N(2)); + [xx,yy] = ndgrid(xx,yy); + center = L/2; + radius = 0.06*L(1); + thickness = 0.01*L(1); + roi = roi_circle(xx,yy,center,radius,thickness); + + %nucleus + y0 = y1(end,:)'; + roi = roi(:); + y02 = 0.045; + rho = (y02*n - sum(roi.*y0)) / sum(1-roi); + y0 = roi.*y0 + (1-roi)*rho; + + tspan2 = linspace(0,2.5,100); + [t2,y2] = solver_DDFT(tspan2,y0,params); + toc +end + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); + +kernelSize = 50; +Cspace = 'isotropic_cutoff'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation24.mat']; + +[hessian,hessian_t,dy] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],[],'discrete',true,'cutoff',30,'assign_suppress',{'C'},'mode','sens'); diff --git a/solver/DDFT_nucleation25.m b/solver/DDFT_nucleation25.m new file mode 100644 index 0000000..48d0c3e --- /dev/null +++ b/solver/DDFT_nucleation25.m @@ -0,0 +1,66 @@ +%based on DDFT_nucleation15 +%use a different time range +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 4; +Cspace = 'isotropic_cutoff'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation25.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +if runoptim + x_guess = [0,0,0,0,0.3,0,-3]; + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'tspan',300,'cutoff',30); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + modelfunc.mu = @(x) x - x.^2/2 + x.^3/3; + arg.C = linspace(0,2,500); + arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); + frameindex = 1:20:100; + history_production(resultpath,[1,21,45,125],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'FrameIndex',frameindex,'IP_DDFT_arg',{'Nmu',3},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',[min(ydata(:)),2]); + f = gcf; + f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation26.m b/solver/DDFT_nucleation26.m new file mode 100644 index 0000000..cce32b8 --- /dev/null +++ b/solver/DDFT_nucleation26.m @@ -0,0 +1,57 @@ +%based on DDFT_nucleation15 +%isotropic_poly_scale +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 5; +Cspace = 'isotropic_poly_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation26.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [0,0,0,0,0];%,0.5,0,-3]; + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',0,'tspan',300,'cutoff',30); diff --git a/solver/DDFT_nucleation27.m b/solver/DDFT_nucleation27.m new file mode 100644 index 0000000..77ae5f7 --- /dev/null +++ b/solver/DDFT_nucleation27.m @@ -0,0 +1,57 @@ +%based on DDFT_nucleation26 +%kernelSize=7 (up to 6th order) +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 7; +Cspace = 'isotropic_poly_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation27.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = zeros(1,kernelSize); + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',0,'tspan',300,'cutoff',30); diff --git a/solver/DDFT_nucleation28.m b/solver/DDFT_nucleation28.m new file mode 100644 index 0000000..40ac647 --- /dev/null +++ b/solver/DDFT_nucleation28.m @@ -0,0 +1,57 @@ +%based on DDFT_nucleation15 +%isotropic_poly_scale with isotropic_even = true +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 3; +Cspace = 'isotropic_poly_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation28.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = zeros(1,kernelSize); + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',0,'tspan',300,'cutoff',2*k0,'isotropic_even',true); diff --git a/solver/DDFT_nucleation29.m b/solver/DDFT_nucleation29.m new file mode 100644 index 0000000..b5647ff --- /dev/null +++ b/solver/DDFT_nucleation29.m @@ -0,0 +1,57 @@ +%based on DDFT_nucleation15 +%Cspace = isotropic_hermite_scale +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 6; +Cspace = 'isotropic_hermite_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation29.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = zeros(1,kernelSize); + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',0,'tspan',300,'cutoff',k0); diff --git a/solver/DDFT_nucleation2_helper.m b/solver/DDFT_nucleation2_helper.m new file mode 100644 index 0000000..b910520 --- /dev/null +++ b/solver/DDFT_nucleation2_helper.m @@ -0,0 +1,11 @@ +addpath('../../CHACR/GIP'); +save_history = true; +resultpath = [largedatapath,'DDFT_nucleation2.mat']; +varload = load(resultpath); +x_opt = varload.history(end,:); +exitflag = 5; +options = optimoptions('fminunc','OutputFcn',@(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath,[],true)); + +while (exitflag==5) + [x_opt,~,exitflag] = IP_DDFT(tdata,ydata,params,[21,21],'k',options,x_opt); +end diff --git a/solver/DDFT_nucleation3.m b/solver/DDFT_nucleation3.m new file mode 100644 index 0000000..587418d --- /dev/null +++ b/solver/DDFT_nucleation3.m @@ -0,0 +1,68 @@ +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,1.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:50; +tdata1 = t2(ind); +ydata1 = y2(ind,:); +ind = 50:100; +tdata2 = t2(ind); +ydata2 = y2(ind,:); +toc + +kernelSize = [41,41]; +Cspace = 'k'; + +resultpath = [largedatapath,'DDFT_nucleation3.mat']; +if runoptim + save_history = true; + options = optimoptions('fminunc','MaxIterations',5); + if save_history + options = optimoptions(options,'OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath,[],true)); + end + NC = floor((prod(kernelSize)+1)/2); + x_opt = zeros(1,NC); + while true + x_opt = IP_DDFT(tdata1,ydata1,params,kernelSize,Cspace,options,x_opt,'tspan',200); + x_opt = IP_DDFT(tdata2,ydata2,params,kernelSize,Cspace,options,x_opt,'tspan',200); + end +else + meta.C.index = floor((prod(kernelSize)+1)/2); + meta.C.exp = false; + frameindex = [1,6,12,23,41]; + history_production(resultpath,[1,2,11,71,171],[],[],meta,tdata-tdata(1),ydata,params,kernelSize,Cspace,'FrameIndex',frameindex,'CtruthSubplot',[2,length(frameindex)]); + f = gcf; + f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation30.m b/solver/DDFT_nucleation30.m new file mode 100644 index 0000000..8505e48 --- /dev/null +++ b/solver/DDFT_nucleation30.m @@ -0,0 +1,65 @@ +%based on DDFT_nucleation29 +%5 snapshots. kernelSize = 10 +addpath('../../CHACR/GIP') +runoptim = false; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 10; +Cspace = 'isotropic_hermite_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation30.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +if runoptim + x_guess = zeros(1,kernelSize); + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',0,'discrete',true,'cutoff',k0); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + Crange = [0,4]; + arg.C = linspace(Crange(1),Crange(2),500); + history_production(resultpath,[1,11,21,36],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'IP_DDFT_arg',{'Nmu',0,'discrete',true,'cutoff',k0},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',Crange); + % f = gcf; + % f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation30_DILI.m b/solver/DDFT_nucleation30_DILI.m new file mode 100644 index 0000000..fe2d214 --- /dev/null +++ b/solver/DDFT_nucleation30_DILI.m @@ -0,0 +1,151 @@ +%based on DDFT_nucleation29 +%5 snapshots. kernelSize = 10 +addpath('../../CHACR/GIP') +rundili = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +modelfunc = @(x) exp(-(x-k0).^2/(2*alpha^2))*0.95; +params.C = modelfunc(sqrt(k2)); + +if ~exist('y1','var') + [t1,y1,params] = solver_DDFT([],[],params); + + xx = linspace(0,L(1),N(1)); + yy = linspace(0,L(2),N(2)); + [xx,yy] = ndgrid(xx,yy); + center = L/2; + radius = 0.06*L(1); + thickness = 0.01*L(1); + roi = roi_circle(xx,yy,center,radius,thickness); + + %nucleus + y0 = y1(end,:)'; + roi = roi(:); + y02 = 0.045; + rho = (y02*n - sum(roi.*y0)) / sum(1-roi); + y0 = roi.*y0 + (1-roi)*rho; + + tspan2 = linspace(0,2.5,100); + [t2,y2] = solver_DDFT(tspan2,y0,params); +end + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 10; +Cspace = 'user'; +%params.moreoptions = moreodeset('gmresTol',1e-5); + +%basis function here is hermitefunction scaled by 1/sqrt(eigenvalue), where eigenvalue is (2n+1) as in x^2 y(x) - y''_n(x) = (2n+1) y_n(x) +% customfunc = @(x) hermitefunction(x/k0,kernelSize,[],1) ./ sqrt(1:2:(2*kernelSize-1)); +%get mu parameters at truth +% xfit = linspace(0,3*k0,20)'; +% x_start = customfunc(xfit) \ modelfunc(xfit); +%provide Csensval + +%I changed my mind, just use normalized hermitefunction, so prior is just exp(-||C(k)||_2^2/2) +customfunc = @(x) hermitefunction(x/k0,kernelSize,[],1); +k = sqrt(k2); +params.Csensval = reshape(customfunc(k(:)), [size(k),kernelSize]); + +logpdf = @(x) IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],x,'Nmu',0,'discrete',true,'cutoff',k0,'mode','fgh'); + +% name = 'DDFT_nucleation30_DILI_MAP'; +% resultpath = [largedatapath,name,'.mat']; +% if ~exist(resultpath,'file') +% %find MAP +% x_guess = zeros(1,kernelSize); +% optoptions = optimoptions('fminunc','SpecifyObjectiveGradient',true,'Display','iter-detailed','MaxIterations',50,'StepTolerance',1e-6,'FunctionTolerance',1e-6,'HessianFcn','objective','Algorithm','trust-region'); +% optoptions = optimoptions(optoptions,'OutputFcn',@(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +% [x_start, Smin] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,optoptions,x_guess,'Nmu',0,'discrete',true,'cutoff',k0); +% else +% varload = load(resultpath); +% x_start = varload.history(end,:); +% end + +%use result from DDFT_nucleation30 directly +varload = load([largedatapath,'DDFT_nucleation30']); +x_start = varload.history(end,:); + +options = []; +options.init = x_start; +options.N = 20000; +options.eigthresh = 0.1; +options.eigthresh_local = 1e-4; +options.tLIS = 0.1; +options.tCS = 1; +options.nlag = 100; +options.nb = 50; %have nlag and nb when constr is used, try see if less infeasible samples are taken +options.nmax = 100; +options.verbose = true; +options.proposal = 'LI_Prior'; +options.sigmae = 1e-4; +options.resultpath = [largedatapath,'DDFT_nucleation30_DILI']; +options.saveperstep = 100; + +rng(1); +if rundili + options.logpdf = logpdf; + [chain,result] = mcmc_DILI(options); +else + darkmode = true; + if darkmode + f = figure('Position',[680 642 392 336],'Color',[0,0,0],'InvertHardCopy','off'); + else + f = figure('Position',[680 642 392 336]); + end + burnin = 100; + p = 0.95; %confidence level + xplot = linspace(0,5*k0,200)'; + varload = load(options.resultpath); + cf.func = @(x,coeff) hermitefunction(x/k0,[],coeff,1); + cf.sens = @(x,coeff) customfunc(x); + yy = linearfuncEval(cf,xplot,varload.chain(burnin:end,:)); + mu = mean(yy,1); + upper = quantile(yy,1-(1-p)/2) - mu; + lower = mu - quantile(yy,(1-p)/2); + + main = axes('Position',[0.18,0.2,0.6,0.7]); + [hl,hp] = boundedline(xplot/k0,mu',[lower;upper].'); + hl.LineWidth = 2; + hold on; + htruth = plot(xplot/k0,modelfunc(xplot),'--k'); + xlabel('k/k_0'); + ylabel('$\hat{C}_2(k)$','Interpreter','latex'); + xlim([0,5]); + if darkmode + htruth.Color = [1,1,1]; + hp.FaceColor=hl.Color*0.4; + end + if darkmode + main.Color = [0,0,0]; + main.XColor = [1,1,1]; + main.YColor = [1,1,1]; + end + + ymin = min(ydata(:)); + ymax = max(ydata(:)); + for i = 1:5 + axes('Position',[0.82,0.1+0.18*(5-i),0.15,0.15]); + imshow((reshape(ydata(i,:),N)-ymin)/(ymax-ymin)); + colormap(flip(gray)); + end + + set(findall(f,'-property','FontName'),'FontName','Arial'); + set(findall(f,'-property','FontWeight'),'FontWeight','normal'); + set(findall(f,'-property','FontSize'),'FontSize',13); + % print(f,['C:\Users\zhbkl\Dropbox (MIT)\Research\Report 6\PaperIPExpand\DDFT_nucleation30_DILI'],'-dpng','-r500'); +end diff --git a/solver/DDFT_nucleation31.m b/solver/DDFT_nucleation31.m new file mode 100644 index 0000000..2d701ad --- /dev/null +++ b/solver/DDFT_nucleation31.m @@ -0,0 +1,57 @@ +%based on DDFT_nucleation29 +%5 snapshots. optimize mu +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 6; +Cspace = 'isotropic_hermite_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation31.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [zeros(1,kernelSize),0.5,0,-3]; + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true,'cutoff',k0); diff --git a/solver/DDFT_nucleation32.m b/solver/DDFT_nucleation32.m new file mode 100644 index 0000000..fd0fabd --- /dev/null +++ b/solver/DDFT_nucleation32.m @@ -0,0 +1,68 @@ +%based on DDFT_nucleation29 +%5 snapshots. optimize mu, kernelSize = 10 +addpath('../../CHACR/GIP') +runoptim = false; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 10; +Cspace = 'isotropic_hermite_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation32.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [zeros(1,kernelSize),0.5,0,-3]; + +if runoptim + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true,'cutoff',k0); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + modelfunc.mu = @(x) x - x.^2/2 + x.^3/3; + Crange = [0,4]; + arg.C = linspace(Crange(1),Crange(2),500); + arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); + history_production(resultpath,[1,10,20,30,40,65],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'IP_DDFT_arg',{'Nmu',3,'discrete',true,'cutoff',k0},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',Crange,'showModelSolution',false); + % f = gcf; + % f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation33.m b/solver/DDFT_nucleation33.m new file mode 100644 index 0000000..6371b57 --- /dev/null +++ b/solver/DDFT_nucleation33.m @@ -0,0 +1,57 @@ +%based on DDFT_nucleation29 +%5 snapshots. optimize mu, kernelSize = 10, mu_positive = false; +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 10; +Cspace = 'isotropic_hermite_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation33.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [zeros(1,kernelSize),0.5,0,-4]; + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true,'cutoff',k0); diff --git a/solver/DDFT_nucleation34.m b/solver/DDFT_nucleation34.m new file mode 100644 index 0000000..bc1b0a6 --- /dev/null +++ b/solver/DDFT_nucleation34.m @@ -0,0 +1,69 @@ +%based on DDFT_nucleation23 +%use scaling cutoff = k0 for Cspace=isotropic +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation34']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000,'FunctionTolerance',1e-7); + +if runoptim + x_guess = [0,0,0.5,0,-3]; + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true,'cutoff',k0); + %below is modified on workstation + x_guess = [0,-9,0.5,0,-3]; + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true,'cutoff',1); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + modelfunc.mu = @(x) x - x.^2/2 + x.^3/3; + arg.C = linspace(0,2,500); + arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); + history_production(resultpath,[1,21,38,1797],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'IP_DDFT_arg',{'Nmu',3},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',[min(ydata(:)),2]); + f = gcf; + f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation35.m b/solver/DDFT_nucleation35.m new file mode 100644 index 0000000..02206cd --- /dev/null +++ b/solver/DDFT_nucleation35.m @@ -0,0 +1,58 @@ +%based on DDFT_nucleation30 +%5 snapshots. kernelSize = 10. Cspace=isotropic_laguerre_scale +%failed +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 6; +Cspace = 'isotropic_laguerre_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation35.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = zeros(1,kernelSize); + +[x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',0,'discrete',true,'cutoff',k0); diff --git a/solver/DDFT_nucleation36.m b/solver/DDFT_nucleation36.m new file mode 100644 index 0000000..77ab2ed --- /dev/null +++ b/solver/DDFT_nucleation36.m @@ -0,0 +1,69 @@ +%based on DDFT_nucleation29 +%5 snapshots. kernelSize = 10 +addpath('../../CHACR/GIP') +runoptim = false; + +resultpath = [largedatapath,'DDFT_nucleation36.mat']; + +if runoptim + tic; + L = [5,5]; + N = [256,256]; + n = prod(N); + + params.N = N; + params.L = L; + + [k2,k] = formk(N,L); + k0 = 10; + alpha = 5; + params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + + [t1,y1,params] = solver_DDFT([],[],params); + + xx = linspace(0,L(1),N(1)); + yy = linspace(0,L(2),N(2)); + [xx,yy] = ndgrid(xx,yy); + center = L/2; + radius = 0.06*L(1); + thickness = 0.01*L(1); + roi = roi_circle(xx,yy,center,radius,thickness); + + %nucleus + y0 = y1(end,:)'; + roi = roi(:); + y02 = 0.045; + rho = (y02*n - sum(roi.*y0)) / sum(1-roi); + y0 = roi.*y0 + (1-roi)*rho; + + tspan2 = linspace(0,2.5,100); + [t2,y2] = solver_DDFT(tspan2,y0,params); + + ind = 1:20:100; + tdata = t2(ind); + ydata = y2(ind,:); + toc + + + kernelSize = 300; + Cspace = 'isotropic_hermite_scale'; + %note 100 is about where hermitefunction still approaches zero as k approaches kmax (N/L*pi) + params.moreoptions = moreodeset('gmresTol',1e-5); + + [hessian,hessian_t,dy] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],[],'discrete',true,'cutoff',k0,'assign_suppress',{'C'},'mode','sens'); + save(resultpath,'hessian','hessian_t','dy'); +else + addpath('../../External/boundedline-pkg/boundedline') + if ~exist('hessian','var') + load(resultpath); + end + numBasis = 100; + epsilon = 0.01*prod(params.L); + x = linspace(0,4,1000)'; + psi = hermitefunction(x,numBasis); + C = psi * ((hessian(1:numBasis,1:numBasis)+epsilon*eye(numBasis))\psi'); + dev = diag(C)/50; + y = exp(-(x-1).^2/(2*(alpha/k0)^2))*0.95; + [hl,hp] = boundedline(x,y,dev); + ylim([-0.5,1.5]) +end diff --git a/solver/DDFT_nucleation37.m b/solver/DDFT_nucleation37.m new file mode 100644 index 0000000..d979efa --- /dev/null +++ b/solver/DDFT_nucleation37.m @@ -0,0 +1,58 @@ +%based on DDFT_nucleation29 +%5 snapshots. kernelSize = 10 +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 300; +Cspace = 'isotropic_fourier_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation37.mat']; + +kmax = floor(params.N(1)/2+1)/params.L(1)*2*pi; +if runoptim + [hessian,hessian_t,dy] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],[],'discrete',true,'cutoff',kmax,'assign_suppress',{'C'},'mode','sens'); + save(resultpath,'hessian','hessian_t','dy'); +else + load(resultpath); +end diff --git a/solver/DDFT_nucleation38.m b/solver/DDFT_nucleation38.m new file mode 100644 index 0000000..40f6ce5 --- /dev/null +++ b/solver/DDFT_nucleation38.m @@ -0,0 +1,67 @@ +%based on DDFT_nucleation37, sensitivity analysis, use Laguerre +addpath('../../CHACR/GIP') +runoptim = false; + +resultpath = [largedatapath,'DDFT_nucleation38.mat']; + +if runoptim + tic; + L = [5,5]; + N = [256,256]; + n = prod(N); + + params.N = N; + params.L = L; + [k2,k] = formk(N,L); + k0 = 10; + alpha = 5; + params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + + [t1,y1,params] = solver_DDFT([],[],params); + + xx = linspace(0,L(1),N(1)); + yy = linspace(0,L(2),N(2)); + [xx,yy] = ndgrid(xx,yy); + center = L/2; + radius = 0.06*L(1); + thickness = 0.01*L(1); + roi = roi_circle(xx,yy,center,radius,thickness); + + %nucleus + y0 = y1(end,:)'; + roi = roi(:); + y02 = 0.045; + rho = (y02*n - sum(roi.*y0)) / sum(1-roi); + y0 = roi.*y0 + (1-roi)*rho; + + tspan2 = linspace(0,2.5,100); + [t2,y2] = solver_DDFT(tspan2,y0,params); + + ind = 1:20:100; + tdata = t2(ind); + ydata = y2(ind,:); + toc + + + kernelSize = 300; + Cspace = 'isotropic_laguerre_scale'; + params.moreoptions = moreodeset('gmresTol',1e-5); + + [hessian,hessian_t,dy] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],[],'discrete',true,'cutoff',k0,'assign_suppress',{'C'},'mode','sens'); + save(resultpath,'hessian','hessian_t','dy'); +else + addpath('../../External/boundedline-pkg') + if ~exist('hessian','var') + load(resultpath); + end + numBasis = 150; + epsilon = 0.004*prod(params.L); + x = linspace(0,5,1000)'; + psi = laguerrepoly(x,numBasis) .* exp(-x/2); + C = psi * ((hessian(1:numBasis,1:numBasis)+epsilon*eye(numBasis))\psi'); + dev = diag(C); + y = exp(-(x-1).^2/(2*(alpha/k0)^2))*0.95; + figure; + boundedline(x,y,dev/50); + ylim([-0.5,1.5]) +end diff --git a/solver/DDFT_nucleation39.m b/solver/DDFT_nucleation39.m new file mode 100644 index 0000000..6295c26 --- /dev/null +++ b/solver/DDFT_nucleation39.m @@ -0,0 +1,65 @@ +%based on DDFT_nucleation30 +%2 snapshots. kernelSize = 10 +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = [1,41]; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 10; +Cspace = 'isotropic_hermite_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation39.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +if runoptim + x_guess = zeros(1,kernelSize); + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',0,'discrete',true,'cutoff',k0); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + Crange = [0,4]; + arg.C = linspace(Crange(1),Crange(2),500); + history_production(resultpath,[1,11,21,36],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'IP_DDFT_arg',{'Nmu',0,'discrete',true,'cutoff',k0},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',Crange); + % f = gcf; + % f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation4.m b/solver/DDFT_nucleation4.m new file mode 100644 index 0000000..427c75d --- /dev/null +++ b/solver/DDFT_nucleation4.m @@ -0,0 +1,54 @@ +%data from DDFT_nucleation3 +%use PFC to fit +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,1.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 10:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +kernelSize = 3; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation4.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +x_guess = [0,0,-10]; +[x_opt,~,exitflag] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess); diff --git a/solver/DDFT_nucleation40.m b/solver/DDFT_nucleation40.m new file mode 100644 index 0000000..7840e53 --- /dev/null +++ b/solver/DDFT_nucleation40.m @@ -0,0 +1,71 @@ +%based on DDFT_nucleation30 +%5 snapshots. Cspace = 'k' +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = [41,41]; +NC = floor((prod(kernelSize)+1)/2); +Cspace = 'k'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation40.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath,[],true)); +options = optimoptions(options,'MaxFunctionEvaluations',10000,'MaxIterations',10000); + +if runoptim + x_opt = zeros(1,NC); + exitflag = 5; + while (exitflag==5) + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_opt,'Nmu',0,'discrete',true); + %below is used by workstation + [x_opt,~,exitflag] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_opt,'Nmu',0,'discrete',true); + end +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + Crange = [0,4]; + arg.C = linspace(Crange(1),Crange(2),500); + history_production(resultpath,[1,11,21,36],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'IP_DDFT_arg',{'Nmu',0,'discrete',true,'cutoff',k0},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',Crange); + % f = gcf; + % f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation41.m b/solver/DDFT_nucleation41.m new file mode 100644 index 0000000..ce0b665 --- /dev/null +++ b/solver/DDFT_nucleation41.m @@ -0,0 +1,89 @@ +%based on DDFT_nucleation32 +%change x_guess(1) to 0.1 +addpath('../../CHACR/GIP') +runoptim = false; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 10; +Cspace = 'isotropic_hermite_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation41_ally.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [zeros(1,kernelSize),0.5,0,-3]; +x_guess(1) = 0.1; + +if runoptim + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true,'cutoff',k0); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + modelfunc.mu = @mu; + Crange = [0,4]; + arg.C = linspace(Crange(1),Crange(2),500); + arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); + % history_production(resultpath,[],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,... + % 'IP_DDFT_arg',{'Nmu',3,'discrete',true,'cutoff',k0},'yyaxisLim',[-0.5,1.5;0,2],... + % 'k0',k0,'xlim',[min(ydata(:)),Crange(2)],'showModelSolution',true,'offset',true,'muderiv',true,... + % 'legend',{{'$\hat{C_2}(k)$ (truth)','$\hat{C_2}(k)$','$\mu_h(\eta)$ (truth)','$\mu_h(\eta)$'},... + % 'Orientation','horizontal','Position',[0.2051 0.001 0.7874 0.0566],'Interpreter','latex'},... + % 'FontSize',13,'stparg',{0.05,[0.1,0.08],[0.08,0.04]}); + % f = gcf; + % f.Position = [680 368 588 610]; + + figure('Color',[0,0,0],'Position',[593 189 1036 610],'InvertHardCopy','off'); + mv = VideoWriter('DDFT_nucleation41','MPEG-4'); + mv.FrameRate = 1; + history_movie(resultpath,mv,[],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,... + 'yyaxisLim',[0.6,1.7;-0.2,1.2],'funcxlabel',false,'FontSize',14,... + 'visualizeArgs',{'edgeColor',[1,1,1],'edgeWidth',1,'colormap',colormap(gray)},... + 'k0',k0,'IP_DDFT_arg',{'Nmu',3,'discrete',true,'cutoff',k0},... + 'use_saved',true,'save',false,'muderiv',true,'offset',true,... + 'stparg',{[0.03,0.03],[0.05,0.15],0.08},'labelpos',[-0.3,1.6]); +end + +function [y,dy] = mu(x) + y = x - x.^2/2 + x.^3/3; + dy = 1 - x + x.^2; +end diff --git a/solver/DDFT_nucleation42.m b/solver/DDFT_nucleation42.m new file mode 100644 index 0000000..f157895 --- /dev/null +++ b/solver/DDFT_nucleation42.m @@ -0,0 +1,68 @@ +%based on DDFT_nucleation32 +%change x_guess the first coeff for mu to 0.6 from 0.5 +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 10; +Cspace = 'isotropic_hermite_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation42.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [zeros(1,kernelSize),0.6,0,-3]; + +if runoptim + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true,'cutoff',k0); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + modelfunc.mu = @(x) x - x.^2/2 + x.^3/3; + Crange = [0,4]; + arg.C = linspace(Crange(1),Crange(2),500); + arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); + history_production(resultpath,[1,10,20,30,40,65],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'IP_DDFT_arg',{'Nmu',3,'discrete',true,'cutoff',k0},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',Crange,'showModelSolution',false); + % f = gcf; + % f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation42_bgs.m b/solver/DDFT_nucleation42_bgs.m new file mode 100644 index 0000000..a3c46c4 --- /dev/null +++ b/solver/DDFT_nucleation42_bgs.m @@ -0,0 +1,80 @@ +%based on DDFT_nucleation41 +%change mu third order guess to 0 +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +%[t1,y1,params] = solver_DDFT([],[],params); +% +%xx = linspace(0,L(1),N(1)); +%yy = linspace(0,L(2),N(2)); +%[xx,yy] = ndgrid(xx,yy); +%center = L/2; +%radius = 0.06*L(1); +%thickness = 0.01*L(1); +%roi = roi_circle(xx,yy,center,radius,thickness); +% +%%nucleus +%y0 = y1(end,:)'; +%roi = roi(:); +%y02 = 0.045; +%rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +%y0 = roi.*y0 + (1-roi)*rho; +% +%tspan2 = linspace(0,2.5,100); +%[t2,y2] = solver_DDFT(tspan2,y0,params); +% +%ind = 1:20:100; +%tdata = t2(ind); +%ydata = y2(ind,:); +%toc + + +kernelSize = 10; +Cspace = 'isotropic_hermite_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation41.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [zeros(1,kernelSize),0.5,0,-6]; +x_guess(1) = 0.1; + +if runoptim + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true,'cutoff',k0); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + modelfunc.mu = @mu; + Crange = [0,4]; + arg.C = linspace(Crange(1),Crange(2),500); + arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); + history_production(resultpath,[1,11,36,58],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,... + 'IP_DDFT_arg',{'Nmu',3,'discrete',true,'cutoff',k0},'yyaxisLim',[-0.5,1.5;0,2],... + 'k0',k0,'xlim',[min(ydata(:)),Crange(2)],'showModelSolution',true,...%'offset',true,'muderiv',true,... + 'legend',{{'$\hat{C_2}(k)$ (truth)','$\hat{C_2}(k)$','$\mu_h(\eta)$ (truth)','$\mu_h(\eta)$'},... + 'Orientation','horizontal','Position',[0.2051 0.001 0.7874 0.0566],'Interpreter','latex'},... + 'FontSize',13,'stparg',{0.05,[0.1,0.08],[0.08,0.04]}); + f = gcf; + f.Position = [680 368 588 610]; +end + +function [y,dy] = mu(x) + y = x - x.^2/2 + x.^3/3; + dy = 1 - x + x.^2; +end + diff --git a/solver/DDFT_nucleation43.m b/solver/DDFT_nucleation43.m new file mode 100644 index 0000000..4af2892 --- /dev/null +++ b/solver/DDFT_nucleation43.m @@ -0,0 +1,68 @@ +%based on DDFT_nucleation32 +%change x_guess the first coeff for mu to 0.4 from 0.5 +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,2.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 1:20:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + + +kernelSize = 10; +Cspace = 'isotropic_hermite_scale'; +params.moreoptions = moreodeset('gmresTol',1e-5); + + +resultpath = [largedatapath,'DDFT_nucleation43.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region','MaxFunctionEvaluations',10000,'MaxIterations',10000); + +x_guess = [zeros(1,kernelSize),0.4,0,-3]; + +if runoptim + [x_opt,~,exitflag,params] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3,'discrete',true,'cutoff',k0); +else + modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; + modelfunc.mu = @(x) x - x.^2/2 + x.^3/3; + Crange = [0,4]; + arg.C = linspace(Crange(1),Crange(2),500); + arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); + history_production(resultpath,[1,10,20,30,40,65],modelfunc,arg,tdata-tdata(1),ydata,params,kernelSize,Cspace,'IP_DDFT_arg',{'Nmu',3,'discrete',true,'cutoff',k0},'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',Crange,'showModelSolution',false); + % f = gcf; + % f.Position = [680 337 522 641]; +end diff --git a/solver/DDFT_nucleation5.m b/solver/DDFT_nucleation5.m new file mode 100644 index 0000000..e60cf64 --- /dev/null +++ b/solver/DDFT_nucleation5.m @@ -0,0 +1,55 @@ +%data from DDFT_nucleation3 +%use PFC to fit +%result: stuck at large loss function +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,1.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 10:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +kernelSize = 3; +Cspace = 'FD'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation5.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +x_guess = [0,0,-10]; +[x_opt,~,exitflag] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess); diff --git a/solver/DDFT_nucleation6.m b/solver/DDFT_nucleation6.m new file mode 100644 index 0000000..6f08970 --- /dev/null +++ b/solver/DDFT_nucleation6.m @@ -0,0 +1,58 @@ +%data from DDFT_nucleation3 +%based on DDFT_nucleation4, use 4 derivatives +%use PFC to fit +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,1.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 10:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +kernelSize = 4; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',0.2*1e-5); + +resultpath = [largedatapath,'DDFT_nucleation6.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath,[],true)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +varload = load([largedatapath,'DDFT_nucleation4.mat']); +x_guess = varload.history(end,:); +x_guess(end) = -exp(x_guess(end)); +x_guess = [x_guess,-10]; +[x_opt,~,exitflag] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess); diff --git a/solver/DDFT_nucleation7.m b/solver/DDFT_nucleation7.m new file mode 100644 index 0000000..8c83d86 --- /dev/null +++ b/solver/DDFT_nucleation7.m @@ -0,0 +1,56 @@ +%data from DDFT_nucleation3 +%use PFC to fit +%based on DDFT_nucleation4, where we found the result is insensitive to the 4th order +%use a larger value for initial guess of 4th order coefficient +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,1.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 10:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +kernelSize = 3; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation7.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath,[],true)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +x_guess = [0,0,-5]; +[x_opt,~,exitflag] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess); diff --git a/solver/DDFT_nucleation8.m b/solver/DDFT_nucleation8.m new file mode 100644 index 0000000..6a87efe --- /dev/null +++ b/solver/DDFT_nucleation8.m @@ -0,0 +1,55 @@ +%data from DDFT_nucleation3 +%Cspace = 'isotropic_CmE' +%stuck at 2nd iteration model eval because C is positive at large k +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,1.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 10:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +kernelSize = 4; +Cspace = 'isotropic_CmE'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation8.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +x_guess = [1,0,0,0]; +[x_opt,~,exitflag] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'bound',[0,20^2]); diff --git a/solver/DDFT_nucleation9.m b/solver/DDFT_nucleation9.m new file mode 100644 index 0000000..814a9e7 --- /dev/null +++ b/solver/DDFT_nucleation9.m @@ -0,0 +1,54 @@ +%data from DDFT_nucleation3 +%use PFC to fit, fit C and mu +addpath('../../CHACR/GIP') +runoptim = true; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,1.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); + +ind = 10:100; +tdata = t2(ind); +ydata = y2(ind,:); +toc + +kernelSize = 3; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); + +resultpath = [largedatapath,'DDFT_nucleation9.mat']; + +options = optimoptions('fminunc','OutputFcn', @(x,optimvalues,state) save_opt_history(x,optimvalues,state,resultpath)); +options = optimoptions(options,'HessianFcn','objective','Algorithm','trust-region'); + +x_guess = [0,0,-10]; +[x_opt,~,exitflag] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,options,x_guess,'Nmu',3); diff --git a/solver/DDFT_nucleation_PFC.m b/solver/DDFT_nucleation_PFC.m new file mode 100644 index 0000000..a9061f5 --- /dev/null +++ b/solver/DDFT_nucleation_PFC.m @@ -0,0 +1,38 @@ +addpath('../../CHACR/GIP') +runoptim = false; + +tic; +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = - (1-(k2/k0^2)).^2 + 0.95; + +[t1,y1,params] = solver_DDFT([],[],params); + +% params.C = []; +% [t2,y2,params] = solver_DDFT([],[],params); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = ndgrid(xx,yy); +center = L/2; +radius = 0.06*L(1); +thickness = 0.01*L(1); +roi = roi_circle(xx,yy,center,radius,thickness); + +%nucleus +y0 = y1(end,:)'; +roi = roi(:); +y02 = 0.045; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan2 = linspace(0,1.5,100); +[t2,y2] = solver_DDFT(tspan2,y0,params); diff --git a/solver/DDFT_nucleus.m b/solver/DDFT_nucleus.m new file mode 100644 index 0000000..66105e7 --- /dev/null +++ b/solver/DDFT_nucleus.m @@ -0,0 +1,51 @@ +%parameter search +L = [5,5]*2; +N = [256,256]; +n = prod(N); +n0 = 0.07; +sigma = 0.01; + +rng(1); +n0 = n0 + sigma*randn(N); +y0 = fftn(n0); +y0 = y0(:); + + +[k2,k] = formk(N,L); +k2 = k2(:); +kind1 = k{1}; kind2 = k{2}; +[kind1,kind2] = ndgrid(kind1(:),kind2(:)); +theta = angle(kind1+i*kind2); + +theta = theta(:); + +k0 = 10; +alpha = 2; +C2 = exp(-(sqrt(k2)-k0).^2/(2*alpha^2)); +J = -k2.*(-C2); + +tspan = linspace(0,1.08,100); +options = odeset('AbsTol',1e-3); +[tout,yout] = odeimex(@(t,y) DDFT_nlin(t,y,k2,N),J,tspan,y0); + +y0 = ifftn(reshape(yout(:,end),N)); + +xx = linspace(0,L(1),N(1)); +yy = linspace(0,L(2),N(2)); +[xx,yy] = meshgrid(xx,yy); + +roi = 1./(1+exp(-(xx-0.64*L(1))/0.1)) .* 1./(1+exp((yy-0.4*L(2))/0.1)); +rho = (sum(y0(:)) - sum(roi(:).*y0(:))) / sum(1-roi(:)); +y0new = roi.*y0 + (1-roi)*rho; +%interpolate +y0new = imresize(y0new,2); +y0new = fftn(y0new); +y0new = y0new(:); +N = [256,256]*2; +figure; k2real(y0new,N); + +save('DDFT_nucleus','y0new'); + +tspan2 = linspace(0,1,100); +options = odeset('AbsTol',1e-3); +[tout2,yout2] = odeimex(@(t,y) DDFT_nlin(t,y,k2,N),J,tspan2,y0new); diff --git a/solver/DDFT_nucleus.mat b/solver/DDFT_nucleus.mat new file mode 100644 index 0000000..1ea4b24 Binary files /dev/null and b/solver/DDFT_nucleus.mat differ diff --git a/solver/FDcoeff.m b/solver/FDcoeff.m new file mode 100644 index 0000000..5c9dfc4 --- /dev/null +++ b/solver/FDcoeff.m @@ -0,0 +1,27 @@ +function y = FDcoeff(npts,h,deriv,x) + %coefficients of 1D finite difference + %ntps: number of points, h: distance + %deriv: coefficients of the derivatives. It can be a 1D array, or if 2D, each column is a set of coefficient + %in increasing order 0 through npts-1 + %for example, to get 4th order derivative, deriv = [0;0;0;0;1] + %to get 2nd and 4th, deriv = [0,0;0,0;1,0;0,0;0,1]; + %if x is provided, x is the positions of the points, discarding npts and h information + if nargin < 4 || isempty(x) + n = (npts-1)/2; + x = h*(-n:n); + elseif size(x,2)==1 + x = x'; + npts = size(x,2); + end + if size(deriv,1)==1 + deriv = deriv'; + end + if size(deriv,1)0 + %throw the constant term to mu, note that kernelSize is now the number of non-constant polynomials + Csensval = feval(p.sens,k2,ones(1,NC+1)); + Csensval(:,:,1) = []; + else + Csensval = feval(p.sens,k2,ones(1,NC)); + end + %let the basis of the last derivative be negative + Csensval(:,:,end) = -Csensval(:,:,end); + params.Csensval = Csensval; +case {'isotropic_cos_cutoff','isotropic_cos_scale'} + NC = kernelSize; + meta.C.exp = false; + [k2,~] = formk(params.N,params.L); + k = sqrt(k2)/cutoff; + %use cos((n+1/2)*pi*k/cutoff) + Csensval = ones(size(k,1),size(k,2),NC); + if Nmu > 0 + for i = 1:NC + Csensval(:,:,i) = cos((i-1/2)*pi*k); + end + else + for i = 2:NC + Csensval(:,:,i) = cos((i-3/2)*pi*k); + end + end + mask = 1*(k<=1); + params.Csensval = Csensval .* mask; +case {'isotropic_fourier_scale'} + NC = kernelSize; + meta.C.exp = false; + [k2,~] = formk(params.N,params.L); + k = sqrt(k2)/cutoff; + Csensval = ones(size(k,1),size(k,2),NC); + if Nmu > 0 + Ncos = ceil((NC-1)/2); + Nsin = NC-1-Ncos; + NcosInd(1,1,:) = 1:Ncos; + NsinInd(1,1,:) = 1:Nsin; + Csensval(:,:,2:2:(2*Ncos)) = cos(NcosInd*pi.*k); + Csensval(:,:,3:2:(2*Nsin+1)) = sin(NsinInd*pi.*k); + else + Ncos = ceil(NC/2); + Nsin = NC-Ncos; + NcosInd(1,1,:) = 1:Ncos; + NsinInd(1,1,:) = 1:Nsin; + Csensval(:,:,1:2:(2*Ncos-1)) = cos(NcosInd*pi.*k); + Csensval(:,:,2:2:(2*Nsin)) = sin(NsinInd*pi.*k); + end + mask = 1*(k<=1); + params.Csensval = Csensval .* mask; +case {'isotropic_poly_cutoff','isotropic_poly_scale'} + %NB: we use |k| as the argument of Legenre polynomials + %scale k by cutoff, if using poly_cutoff, beyond cutoff, C is set to zero. + %Legendre polynomial on [0,1]. Consider using even polynomials. + NC = kernelSize; + meta.C.exp = false; + [k2,~] = formk(params.N,params.L); + k = sqrt(k2)/cutoff; + if Nmu>0 + %throw the constant term to mu, note that kernelSize is now the number of non-constant polynomials + nval = NC+1; + else + nval = NC; + end + if isotropic_even + nval = 2*nval-1; + end + Csensval = legendrepoly(k,nval,[],1); + if isotropic_even + Csensval(:,:,2*(1:floor(nval/2))) = []; + end + if Nmu>0 + Csensval(:,:,1) = []; + Csensval = Csensval-1; + else + Csensval(:,:,2:end) = Csensval(:,:,2:end)-1; + end + if isequal(Cspace,'isotropic_poly_cutoff') + Csensval = Csensval .* (1*(k<=1)); + end + params.Csensval = Csensval; +case 'isotropic_hermite_scale' + %|k| scaled by cutoff + NC = kernelSize; + meta.C.exp = false; + [k2,~] = formk(params.N,params.L); + k = sqrt(k2)/cutoff; + params.Csensval = hermitefunction(k,NC,[],1); +case 'isotropic_laguerre_scale' + %|k| scaled by cutoff + NC = kernelSize; + meta.C.exp = false; + [k2,~] = formk(params.N,params.L); + k = sqrt(k2)/cutoff; + params.Csensval = laguerrepoly(k,NC,[],0,1) .* exp(-k/2); +case 'isotropic_CmE' + %constant minus exponential + NC = kernelSize; + meta.C.exp = false; + [k2,~] = formk(params.N,params.L); + k2 = k2/cutoff^2; + if isempty(ps.Results.bound) + bound = [0,max(k2(:))]; + else + bound = ps.Results.bound; + end + expleg = custom_ExpLegendre(1,bound); + if Nmu>0 + %minus exponential only + params.Cfunc.func = @(coeff) -expleg.func(k2,coeff); + params.Cfunc.sens = @(coeff) -expleg.sens(k2,coeff); + else + params.Cfunc.func = @(coeff) coeff(1)-expleg.func(k2,coeff(2:end)); + params.Cfunc.sens = @(coeff) CmE_sens(k2,coeff,expleg.sens); + end +case 'FD' + NC = kernelSize; + meta.C.exp = false(1,NC); + meta.C.exp(end) = true; + params = FD2otf(NC,params); +case 'user' + NC = kernelSize; + meta.C.exp = false; +otherwise + NC = floor((prod(kernelSize)+1)/2); + params.Csens = @(y,i) Csens_ASA(y,i,Cspace,kernelSize); + meta.C.exp = false; +end + +meta.C.index = 1:NC; +if nargin < 7 || isempty(x_guess) + x_guess = zeros(1,NC); +end + +numParams = NC; +if Nmu>0 + meta.mu.index = numParams+(1:Nmu); + meta.mu.exp = false(1,Nmu); + if mu_positive + meta.mu.exp(end) = true; %the coefficient of the higher odd order term must be positive + end + params.mu = ChemPotential_Legendre(1,ybound,false,'onlyEnthalpy'); + if length(x_guess)<(numParams+Nmu) + mu_guess = zeros(1,Nmu); + mu_guess(1) = 2; + %the following makes mu nonmonotonic if Nmu>1 + % mu_guess = [zeros(1,Nmu-1),1]; + % [~,dmu] = feval(params.mu.func,ybound(2),mu_guess); + % %set the gradient at ybound to be 2 + % mu_guess(end) = log(2/dmu); + x_guess = [x_guess(1:numParams), mu_guess]; + end + numParams = NC+Nmu; +end + +if ps.Results.D + meta.D.index = numParams+1; + meta.D.exp = true; + if length(x_guess)<(numParams+1) + D_guess = -3; + x_guess = [x_guess(1:numParams), D_guess]; + end +end + +forwardHandle = @(tdata,y0,FSA,meta,params) forwardSolver(tdata,y0,FSA,meta,params,tspan,ybound); +assignHandle = @(name,xparam,params) assign(name,xparam,params,Cspace,kernelSize); +switch mode +case 'eval' + [x_opt,~,params] = IP(tdata,ydata,x_guess,meta,params, ... + forwardHandle, [], [], [], assignHandle,'eval',true); + fval = []; + exitflag = []; +case 'fgh' + loss = @(y,ydata,~) MSE(y,ydata,prod(params.dx)); + lossHess = @(dy,~,~,~) MSE([],[],prod(params.dx),dy); + switch nargout + case 1 + x_opt = IP(tdata,ydata,x_guess,meta,params, ... + forwardHandle, @adjointSolver,loss,lossHess, assignHandle, varargin{:}); + case 2 + [x_opt,fval] = IP(tdata,ydata,x_guess,meta,params, ... + forwardHandle, @adjointSolver,loss,lossHess, assignHandle, 'ASA',false,varargin{:}); + case 3 + [x_opt,fval,exitflag] = IP(tdata,ydata,x_guess,meta,params, ... + forwardHandle, @adjointSolver,loss,lossHess, assignHandle, 'ASA',false,varargin{:}); + end +case 'IP' + loss = @(y,ydata,~) MSE(y,ydata,prod(params.dx)*100); + lossHess = @(dy,~,~,~) MSE([],[],prod(params.dx)*100,dy); + if nargin > 5 && ~isempty(options) + options = optimoptions(options,'SpecifyObjectiveGradient',true,'Display','iter-detailed'); + else + options = optimoptions('fminunc','SpecifyObjectiveGradient',true,'Display','iter-detailed'); + end + [x_opt,fval,exitflag] = fminunc(@(x) IP(tdata,ydata,x,meta,params, ... + forwardHandle, @adjointSolver,loss,lossHess, assignHandle,'discrete',discrete), ... + x_guess, options); +case 'sens' + loss = @(y,ydata,~) MSE(y,ydata,prod(params.dx)); + lossHess = @(dy,~,~,~) MSE([],[],prod(params.dx),dy); + [~,~,x_opt,exitflag,fval] = IP(tdata,ydata,x_guess,meta,params, ... + forwardHandle, [],loss,lossHess, ... + @(name,xparam,params) assign(name,xparam,params,Cspace,kernelSize,suppress),'discrete',discrete); +case 'pp' + x_opt = []; + fval = []; + exitflag = []; + params = paramsTransfer(x_guess,meta,params,assignHandle,ydata,false); +end + +if nargout > 3 + %post processing, isotropic_*_cutoff not yet supported + switch Cspace + case 'isotropic' + if Nmu>0 + params.Cfunc.func = @(x,coeff) p.func((x/cutoff).^2,[0,coeff(1:end-1),-coeff(end)]); + else + params.Cfunc.func = @(x,coeff) p.func((x/cutoff).^2,[coeff(1:end-1),-coeff(end)]); + end + case 'isotropic_CmE' + if Nmu>0 + params.Cfunc.func = @(x,coeff) -expleg.func((x/cutoff).^2,coeff); + else + params.Cfunc.func = @(x,coeff) coeff(1)-expleg.func((x/cutoff).^2,coeff(2:end)); + end + case 'isotropic_poly_scale' + if Nmu>0 + params.Cfunc.func = @(x,coeff) legendrepoly(x/cutoff,[],[0,coeff]); + else + params.Cfunc.func = @(x,coeff) legendrepoly(x/cutoff,[],coeff); + end + case 'isotropic_hermite_scale' + params.Cfunc.func = @(x,coeff) hermitefunction(x/cutoff,[],coeff); + case 'isotropic_laguerre_scale' + params.Cfunc.func = @(x,coeff) laguerrepoly(x/cutoff,[],coeff) .* exp(-x/cutoff/2); + end + pp.params = params; + pp.meta = meta; +end + +end + +function params = assign(name,xparam,params,Cspace,kernelSize,suppress) + if nargin>5 && ismember(name,suppress) + return; + end + switch name + case 'mu' + params.(name).params = xparam; + case 'D' + params.(name) = xparam; + case 'C' + %xparam for C is cut in half due to symmetry. + %For the purpose of symmetry, we require that the kernel size be odd in both dimensions + %if a kernel size is even, it is not a symmetric convolution + %If the size of the kernel provided is N(1)*N(2), then the size of xparam is n = floor((prod(N)+1)/2) + %xparam correspond to the first n in the kernel in linear index, + %the rest is obtained using symmetry. This applies to both real space and k space + %Both real space and k space representation is centered at the kernel center (not 1,1) + %but it must be converted to be centered at 1,1 in the k-space representation used in DDFT solver + %consider other extensions: + %1. Reduce to representing 1D C(k) if it's axisymmetric + %Cspace = isotropic, C(k) = a1 + a2*k^2 + a3*k^4 + ... + %Cspace = FD, C = a1 - a2*nabla + a3*nabla^2 + ... + switch Cspace + case 'isotropic_CmE' + params.C = params.Cfunc.func(xparam); + params.Csensval = params.Cfunc.sens(xparam); + params.Cfunc.params = xparam; + case {'k','real'} + if any(mod(kernelSize,2)==0) + error('kernel size must be odd'); + end + n = length(xparam); + if n ~= floor((prod(kernelSize)+1)/2) + error('kernel size incompatible with C input'); + end + %note that n is odd + C = xparam(:); + %symmetry condition + C = [C; flip(C(1:end-1))]; + C = reshape(C, kernelSize); + switch Cspace + case 'k' + % Circularly shift so that the "center" of the OTF is at the + % (1,1) element of the array. (from psf2otf) + padSize = params.N - kernelSize; + C = padarray(C, padSize, 'post'); + C = circshift(C,-floor(kernelSize/2)); + params.C = C; + case 'real' + params.C = psf2otf(C, params.N); + end + otherwise + coeff(1,1,:) = xparam; + params.C = sum(params.Csensval .* coeff,3); + params.Cfunc.params = xparam; + end + end +end + +function [tout,y,dy,params] = forwardSolver(tdata,y0,FSA,meta,params,tspan,ybound) + %tspan can either be sol or number of time points + if ~isfield(params,'mu') || isempty(params.mu) + dmu = 1 - ybound + ybound.^2; + else + dmu = customizeFunGrad(params,'mu','grad',ybound); + end + if any(dmu-max(params.C(:))<0) + %instability even at the max or min y value + tout = NaN; + y = NaN; + dy = NaN; + return + end + switch tspan + case 'sol' + sol = true; + case 'discrete' + sol = false; + otherwise + sol = false; + tdata = linspace(tdata(1),tdata(end),tspan); + end + [tout,y,params,dy] = solver_DDFT(tdata,y0,params,meta,'forward','sol',sol,'FSA',FSA); +end + +function grad = adjointSolver(tdata,sol,lossgrad,meta,discrete,~,params) + grad = solver_DDFT(tdata,sol,params,meta,'adjoint','error',lossgrad,'discrete',discrete); +end + +function dy = Csens(y,Cspace,kernelSize) + %Csens takes up a lot of memory!! Csens is now a function handle for multiplying the sensitivity of C with a vector y. (dy = dC * y) Note that y should in the image format and in real space. + %the returned dy has the dimension of size(y,1)*size(y,2)*number of parameters + %for example, if real space representation is used, use circshift, in sensFcn, + %if k space representation is used, for C(k), the sensitivity of -mu is y(k)exp(ikx)+y(-k)exp(-ikx) + %since y is real, this is equal to 2Re(y(k)exp(ikx)) + %again, note that kernelSize must be odd + n = floor((prod(kernelSize)+1)/2); + kernelCenter = ceil(kernelSize/2); + dy = zeros([size(y),n]); + if isequal(Cspace,'k') + imageSize = size(y); + numPixel = prod(imageSize); + y = fftn(y); + [p1,p2] = ndgrid(0:(imageSize(1)-1),0:(imageSize(2)-1)); + p1 = p1/imageSize(1); + p2= p2/imageSize(2); + end + for i = 1:n + [ind(1),ind(2)] = ind2sub(kernelSize,i); + ind = ind - kernelCenter; + switch Cspace + case 'k' + if all(ind==0) + dy(:,:,i) = y(1,1)/numPixel; + else + if ind(1)>0 + ind(2) = imageSize(2)+ind(2); + else + ind = -ind; + end + %manually implement ifft to be faster see doc for ifftn + dy(:,:,i) = 2*real(y(1+ind(1),1+ind(2)) * exp(2*pi*1i*(p1*ind(1)+p2*ind(2)))/numPixel); + end + % %the following code is another version consistent with the definition of C in assign + % C = zeros(1,n); + % C(i) = 1; + % C = [C,flip(C(1:end-1))]; + % C = reshape(C, kernelSize); + % padSize = imageSize - kernelSize; + % C = padarray(C, padSize, 'post'); + % C = circshift(C,-floor(kernelSize/2)); + % dy(:,:,i) = ifftn(C .* y); + case 'real' + if all(ind==0) + dy(:,:,i) = y; + else + dy(:,:,i) = circshift(y,ind) + circshift(y,-ind); + end + end + end +end + +function dy = Csens_ASA(y,i,Cspace,kernelSize) + %another version of Csens, output only the sensitivity with respect to the ith parameter + %Csens takes up a lot of memory!! Csens is now a function handle for multiplying the sensitivity of C with a vector y. (dy = dC * y) Note that y should in the image format and in real space. + %the returned dy has the dimension of size(y,1)*size(y,2)*number of parameters + %for example, if real space representation is used, use circshift, in sensFcn, + %if k space representation is used, for C(k), the sensitivity of -mu is y(k)exp(ikx)+y(-k)exp(-ikx) + %since y is real, this is equal to 2Re(y(k)exp(ikx)) + %again, note that kernelSize must be odd + n = floor((prod(kernelSize)+1)/2); + kernelCenter = ceil(kernelSize/2); + if isequal(Cspace,'k') + imageSize = size(y); + numPixel = prod(imageSize); + y = fftn(y); + [p1,p2] = ndgrid(0:(imageSize(1)-1),0:(imageSize(2)-1)); + p1 = p1/imageSize(1); + p2= p2/imageSize(2); + end + [ind(1),ind(2)] = ind2sub(kernelSize,i); + ind = ind - kernelCenter; + switch Cspace + case 'k' + if all(ind==0) + dy = y(1,1)/numPixel; + else + if ind(1)>0 + ind(2) = imageSize(2)+ind(2); + else + ind = -ind; + end + %manually implement ifft to be faster see doc for ifftn + dy = 2*real(y(1+ind(1),1+ind(2)) * exp(2*pi*1i*(p1*ind(1)+p2*ind(2)))/numPixel); + end + % %the following code is another version consistent with the definition of C in assign + % C = zeros(1,n); + % C(i) = 1; + % C = [C,flip(C(1:end-1))]; + % C = reshape(C, kernelSize); + % padSize = imageSize - kernelSize; + % C = padarray(C, padSize, 'post'); + % C = circshift(C,-floor(kernelSize/2)); + % dy = ifftn(C .* y); + case 'real' + if all(ind==0) + dy = y; + else + dy = circshift(y,ind) + circshift(y,-ind); + end + end +end + +function params = FD2otf(numDeriv,params) + %transform finite difference coefficient to otf + %y(:,:,i) is the otf of the 2(i-1)th derivative + %in total, there are numDeriv derivatives + npts = numDeriv*2-1; + %switch to 0, k^2, k^4, ... rather than 0, nabla^2, nabla^4 + %but, to be consistent with Cspace = 'isotropic' + %let the basis of the last derivative be negative + derivcoeff = ones(numDeriv,1); + derivcoeff(2:2:end) = -1; + derivcoeff(end) = -1; + derivdiag = accumarray([1:2:npts;1:numDeriv]',derivcoeff); + coeffx = FDcoeff(npts,params.dx(1),derivdiag); + coeffy = FDcoeff(npts,params.dx(2),derivdiag); + row = [numDeriv*ones(1,npts),1:npts]; + column = [1:npts,numDeriv*ones(1,npts)]; + C = zeros(params.N(1),params.N(2),numDeriv); + for i = 1:numDeriv + if i==1 + kernel = 1; + else + kernel = accumarray([row',column'],[coeffx(:,i);coeffy(:,i)]); + end + C(:,:,i) = psf2otf(kernel,params.N); + end + params.Csensval = C; +end + +function y = CmE_sens(x,coeff,expleg_sens) + y = -feval(expleg_sens,x,coeff(2:end)); + y = cat(3,ones(size(x)),y); +end diff --git a/solver/IP_DDFT_debug.m b/solver/IP_DDFT_debug.m new file mode 100644 index 0000000..46b9653 --- /dev/null +++ b/solver/IP_DDFT_debug.m @@ -0,0 +1,218 @@ +function [val,gradient] = IP_DDFT_debug(x_opt,tdata,ydata,params,kernelSize,Cspace,options) + %calculate val and gradient along the x_opt direction +addpath('../../CHACR/GIP') + +% params.N = [256,256]; +% params.L = [5,5]; +% params.dx = params.L ./ params.N; +if isequal(Cspace,'isotropic') + [k2,~] = formk(params.N,params.L); + k = sqrt(k2); +% bound = [0, 2*pi*params.N(1)/params.L(1)/2]; %assuming at least 5 points across each pattern + bound = [0,max(k(:))]; + expleg = custom_Legendre(1,bound); + params.Cfunc.func = @(x) expleg.func(k,x); + params.Cfunc.sens = @(x) expleg.sens(k,x); + NC = kernelSize; +else + NC = floor((prod(kernelSize)+1)/2); + params.Csens = @(y,i) Csens_ASA(y,i,Cspace,kernelSize); +end + +meta.C.index = 1:NC; +meta.C.exp = false; +x_guess = zeros(1,NC); + +tspan = 100; +loss = @(y,ydata,~) MSE(y,ydata,prod(params.dx)*100); +lossHess = @(dy,~,~,~) MSE([],[],prod(params.dx)*100,dy); +if nargin > 6 && ~isempty(options) + options = optimoptions(options,'SpecifyObjectiveGradient',true,'Display','iter-detailed'); +else + options = optimoptions('fminunc','SpecifyObjectiveGradient',true,'Display','iter-detailed'); +end + +Nalpha = 200; +alpha = linspace(0,1,Nalpha); +val = zeros(1,Nalpha); +gradient = zeros(Nalpha,NC); + +parfor i = 1:length(alpha) + [val(i),gradient(i,:)] = IP(tdata,ydata,x_opt*alpha(i),meta,params, ... + @(tdata,y0,FSA,meta,params) forwardSolver(tdata,y0,FSA,meta,params,tspan), ... + @adjointSolver, ... + loss,lossHess, ... + @(name,xparam,params) assign(name,xparam,params,Cspace,kernelSize)); disp(i); +end +end + +function params = assign(name,xparam,params,Cspace,kernelSize) + switch name + case 'mu' + params.(name).params = xparam; + case 'C' + %xparam for C is cut in half due to symmetry. + %For the purpose of symmetry, we require that the kernel size be odd in both dimensions + %if a kernel size is even, it is not a symmetric convolution + %If the size of the kernel provided is N(1)*N(2), then the size of xparam is n = floor((prod(N)+1)/2) + %xparam correspond to the first n in the kernel in linear index, + %the rest is obtained using symmetry. This applies to both real space and k space + %Both real space and k space representation is centered at the kernel center (not 1,1) + %but it must be converted to be centered at 1,1 in the k-space representation used in DDFT solver + %consider other extensions: + %1. Reduce to representing 1D C(k) if it's axisymmetric + if isequal(Cspace,'isotropic') + %C(k) can be represented by a 1D function + params.C = params.Cfunc.func(xparam); + params.Csensval = params.Cfunc.sens(xparam); + else + if any(mod(kernelSize,2)==0) + error('kernel size must be odd'); + end + n = length(xparam); + if n ~= floor((prod(kernelSize)+1)/2) + error('kernel size incompatible with C input'); + end + %note that n is odd + C = xparam(:); + %symmetry condition + C = [C; flip(C(1:end-1))]; + C = reshape(C, kernelSize); + switch Cspace + case 'k' + % Circularly shift so that the "center" of the OTF is at the + % (1,1) element of the array. (from psf2otf) + padSize = params.N - kernelSize; + C = padarray(C, padSize, 'post'); + C = circshift(C,-floor(kernelSize/2)); + params.C = C; + case 'real' + params.C = psf2otf(C, params.N); + end + end + end +end + +function [tout,y,dy,params] = forwardSolver(tdata,y0,FSA,meta,params,tspan) + %tspan can either be sol or number of time points + if any(params.C(:)>2) + tout = NaN; + y = NaN; + dy = NaN; + end + if isequal(tspan,'sol') + sol = true; + else + sol = false; + tdata = linspace(tdata(1),tdata(end),tspan); + end + [tout,y,params,dy] = solver_DDFT(tdata,y0,params,meta,'forward',sol,FSA); +end + +function grad = adjointSolver(tdata,sol,lossgrad,meta,discrete,~,params) + grad = solver_DDFT(tdata,sol,params,meta,'adjoint',lossgrad,discrete); +end + +function dy = Csens(y,Cspace,kernelSize) + %Csens takes up a lot of memory!! Csens is now a function handle for multiplying the sensitivity of C with a vector y. (dy = dC * y) Note that y should in the image format and in real space. + %the returned dy has the dimension of size(y,1)*size(y,2)*number of parameters + %for example, if real space representation is used, use circshift, in sensFcn, + %if k space representation is used, for C(k), the sensitivity of -mu is y(k)exp(ikx)+y(-k)exp(-ikx) + %since y is real, this is equal to 2Re(y(k)exp(ikx)) + %again, note that kernelSize must be odd + n = floor((prod(kernelSize)+1)/2); + kernelCenter = ceil(kernelSize/2); + dy = zeros([size(y),n]); + if isequal(Cspace,'k') + imageSize = size(y); + numPixel = prod(imageSize); + y = fftn(y); + [p1,p2] = ndgrid(0:(imageSize(1)-1),0:(imageSize(2)-1)); + p1 = p1/imageSize(1); + p2= p2/imageSize(2); + end + for i = 1:n + [ind(1),ind(2)] = ind2sub(kernelSize,i); + ind = ind - kernelCenter; + switch Cspace + case 'k' + if all(ind==0) + dy(:,:,i) = y(1,1)/numPixel; + else + if ind(1)>0 + ind(2) = imageSize(2)+ind(2); + else + ind = -ind; + end + %manually implement ifft to be faster see doc for ifftn + dy(:,:,i) = 2*real(y(1+ind(1),1+ind(2)) * exp(2*pi*1i*(p1*ind(1)+p2*ind(2)))/numPixel); + end + % %the following code is another version consistent with the definition of C in assign + % C = zeros(1,n); + % C(i) = 1; + % C = [C,flip(C(1:end-1))]; + % C = reshape(C, kernelSize); + % padSize = imageSize - kernelSize; + % C = padarray(C, padSize, 'post'); + % C = circshift(C,-floor(kernelSize/2)); + % dy(:,:,i) = ifftn(C .* y); + case 'real' + if all(ind==0) + dy(:,:,i) = y; + else + dy(:,:,i) = circshift(y,ind) + circshift(y,-ind); + end + end + end +end + +function dy = Csens_ASA(y,i,Cspace,kernelSize) + %another version of Csens, output only the sensitivity with respect to the ith parameter + %Csens takes up a lot of memory!! Csens is now a function handle for multiplying the sensitivity of C with a vector y. (dy = dC * y) Note that y should in the image format and in real space. + %the returned dy has the dimension of size(y,1)*size(y,2)*number of parameters + %for example, if real space representation is used, use circshift, in sensFcn, + %if k space representation is used, for C(k), the sensitivity of -mu is y(k)exp(ikx)+y(-k)exp(-ikx) + %since y is real, this is equal to 2Re(y(k)exp(ikx)) + %again, note that kernelSize must be odd + n = floor((prod(kernelSize)+1)/2); + kernelCenter = ceil(kernelSize/2); + if isequal(Cspace,'k') + imageSize = size(y); + numPixel = prod(imageSize); + y = fftn(y); + [p1,p2] = ndgrid(0:(imageSize(1)-1),0:(imageSize(2)-1)); + p1 = p1/imageSize(1); + p2= p2/imageSize(2); + end + [ind(1),ind(2)] = ind2sub(kernelSize,i); + ind = ind - kernelCenter; + switch Cspace + case 'k' + if all(ind==0) + dy = y(1,1)/numPixel; + else + if ind(1)>0 + ind(2) = imageSize(2)+ind(2); + else + ind = -ind; + end + %manually implement ifft to be faster see doc for ifftn + dy = 2*real(y(1+ind(1),1+ind(2)) * exp(2*pi*1i*(p1*ind(1)+p2*ind(2)))/numPixel); + end + % %the following code is another version consistent with the definition of C in assign + % C = zeros(1,n); + % C(i) = 1; + % C = [C,flip(C(1:end-1))]; + % C = reshape(C, kernelSize); + % padSize = imageSize - kernelSize; + % C = padarray(C, padSize, 'post'); + % C = circshift(C,-floor(kernelSize/2)); + % dy = ifftn(C .* y); + case 'real' + if all(ind==0) + dy = y; + else + dy = circshift(y,ind) + circshift(y,-ind); + end + end +end diff --git a/solver/LSA.m b/solver/LSA.m new file mode 100644 index 0000000..35108c6 --- /dev/null +++ b/solver/LSA.m @@ -0,0 +1,5 @@ +function y = LSA(A,D) + %whether the input parameters satisfy the pattern forming condition from linear stability analysis (Page 11 of support Kondo paper) + %only support one instance, A is a matrix, D is a vector + y = (trace(A)<0) && (det(A)>0) && (A(1,1)*D(2)+A(2,2)*D(1)>0) && ((A(1,1)*D(2)+A(2,2)*D(1))^2 - 4*D(1)*D(2)*det(A)>0); +end diff --git a/solver/OZ.m b/solver/OZ.m new file mode 100644 index 0000000..54d0600 --- /dev/null +++ b/solver/OZ.m @@ -0,0 +1,22 @@ +function [h,c,hk,ck] = OZ(u,closure,tol) + %solve for C2 and h using Ornstein-Zernike and closure + xi = zeros(size(u)); + while true + switch closure + case 'HNC' + h = exp(-u+xi)-1; + case 'PY' + h = exp(-u) .* (xi+1)-1; + end + hk = psf2otf(h); + hk = -0.8/min(hk(:))*hk; +% hk = fftn(h); + ck = hk./(hk+1); + c = otf2psf(ck); +% c = ifftn(ck,'symmetric'); + xinew = h - c; + if norm(xinew(:)-xi(:)) < tol + break; + end + xi = xinew; + end diff --git a/solver/bd_test.m b/solver/bd_test.m new file mode 100644 index 0000000..06f3fa6 --- /dev/null +++ b/solver/bd_test.m @@ -0,0 +1,18 @@ +D = [0.02,0.5]; +A1 = [0.08,-0.08;0.1,0]; +A2 = -[0.03,0.08]; +mat_ss = matfile('/home/hbozhao/Dropbox (MIT)/2.168 Project/Data/turing_ss'); +A1_ss = mean(mat_ss.A1,1); +A1lb = [-0.5,A1_ss(3);-0.5,A1_ss(4)]; +A1ub = [1.5,A1_ss(3);1.5,A1_ss(4)]; +Anorm = norm(A1+diag(A2),inf); + +ind = 0; +while ind < 10000 + A1new = A1lb + (A1ub-A1lb).*rand(2); + Anew = A1new+diag(A2); + if LSA(Anew,D) && (norm(Anew,inf)<5*Anorm) + ind = ind+1; + Alist(ind,:) = reshape(A1new,1,[]); + end +end diff --git a/solver/dispersion_curve.m b/solver/dispersion_curve.m new file mode 100644 index 0000000..7d68aa5 --- /dev/null +++ b/solver/dispersion_curve.m @@ -0,0 +1,16 @@ +A1 = [0.08,-0.08;0.1,0]; +A2 = -[0.03,0.08]; +A = A1+diag(A2); +D = [0.02,0.5]; + +k = linspace(0,2,1000); +a = 1; +b = (-trace(A)+sum(D)*k.^2); +c = (prod(D)*k.^4-(A(1,1)*D(2)+A(2,2)*D(1))*k.^2+det(A)); +lambda = (-b+[1;-1]*sqrt(b.^2-4*a*c))./(2*a); +figure; +plot(k,max(real(lambda)),'LineWidth',2); +axis([0,2,-0.05,0.02]); +xlabel('|k|'); +ylabel('max Re \lambda') +print(gcf,'C:\Users\zhbkl\Dropbox (MIT)\MIT Courses\2.168\2.168 Project\Final\dispersion','-dpng','-r400'); diff --git a/solver/event_gradient.m b/solver/event_gradient.m new file mode 100644 index 0000000..8859f2a --- /dev/null +++ b/solver/event_gradient.m @@ -0,0 +1,12 @@ +function y = event_gradient(t,y,k2,thresh,component) + %when the L2 norm of the gradient field is below thresh, the returned y is true, otherwise false. + %note that y is in Fourier space. + %L2 norm of the gradient field is \int_{|| \nabla y(x) ||^2 dx} = \int_{|| k ||^2 ||y(k)||^2 dk} + %k2 should correspond to each row of y + %component (1 by default) is the index of the species + if nargin < 5 + component = 1; + end + dy = gradient_norm(y,k2,component); + y = (dy1 + sgind = num2cell(ones(1,dim)); + sgind{end} = ':'; + k{dim}(sgind{:}) = [0:Nmid-1,Nmid-N(dim):-1]'/L(dim)*2*pi; + else + k{dim} = [0:Nmid-1,Nmid-N(dim):-1]'/L(dim)*2*pi; + end + k2 = k2 + k{dim}.^2; +end diff --git a/solver/gradient_norm.m b/solver/gradient_norm.m new file mode 100644 index 0000000..5e36cb2 --- /dev/null +++ b/solver/gradient_norm.m @@ -0,0 +1,11 @@ +function dy = gradient_norm(y,k2,component) + %L2 norm of the gradient field. + %note that y is in Fourier space. + %L2 norm of the gradient field is \int_{|| \nabla y(x) ||^2 dx} = \int_{|| k ||^2 ||y(k)||^2 dk} + %k2 should correspond to each row of y + %component (1 by default) is the index of the species + if nargin < 5 + component = 1; + end + n = length(k2); + dy = norm(k2.*y((component-1)*n+(1:n),:)); diff --git a/solver/history_func.m b/solver/history_func.m new file mode 100644 index 0000000..b9d460e --- /dev/null +++ b/solver/history_func.m @@ -0,0 +1,131 @@ +function history_func(ind,modelfunc,arg,Cspace,pp,property,varargin) + %show the functional forms of history + %pp is the post-processing output from IP_DDFT + %property can be provided directly, if not, through varargin + %ind is the index + if isempty(property) + ps = inputParser; + ps.KeepUnmatched = true; + addParameter(ps,'xlabel','on'); + addParameter(ps,'dmu_at_0',1); %when meta has both mu and C, rescale so that dmu/dx at 0 has this value + addParameter(ps,'k0',1); %used to scale k + addParameter(ps,'yyaxisLim',[]); + addParameter(ps,'xlim',[]); + addParameter(ps,'legend',[]); + addParameter(ps,'label',true); + addParameter(ps,'labelHorizontalAlignment','left'); + addParameter(ps,'targetLineStyle','-.'); + addParameter(ps,'offset',true); %if both C and mu are optimized. Whether to offset C with a constant term and offset mu with a the linear term + addParameter(ps,'muderiv',false); %plot mu'(c) instead of mu + parse(ps,varargin{:}); + ps = ps.Results; + else + ps = property; + end + + meta = pp.meta; + names = fieldnames(meta); + namesflag = ismember({'mu','C'},names); + numFunc = numel(names); + + if all(namesflag) && ps.offset + %calculate current gradient of mu at x=0 + grad0 = customizeFunGrad(pp.params,'mu','grad',0); + %gradient of the first order basis function of mu + [~,grad1] = feval(pp.params.mu.func,0,1); + %set the gradient of mu at x=0 to be 1. The offset is + offset = (ps.dmu_at_0-grad0)/grad1; + pp.params.mu.params(1) = pp.params.mu.params(1) + offset; + + % shift C2 such that C2(0) matches the truth + % offset = modelfunc.C(0) - customizeFunGrad(pp.params,'Cfunc','fun',0); + % pp.params.mu.params(1) = pp.params.mu.params(1) + offset/grad1; + else + offset = 0; + end + ax = gca; + for j=1:numFunc + name = names{j}; + if ismember(name,{'D','extdata'}) + continue; + end + if isequal(name,'C') && ismember(Cspace,{'k','real'}) + imagesc(pp.params.C-offset); + caxis([0,1]); + axis(ax,'image'); + ax.XTick = []; + ax.YTick = []; + ax.Box = 'off'; + else + if isequal(name,'C') && ~isempty(regexp(Cspace,'isotropic*')) + customfunc = pp.params.Cfunc.func; + customparams = pp.params.Cfunc.params; + yoffset = offset; + elseif isequal(name,'mu') + customfunc = pp.params.(name).func; + customparams = pp.params.(name).params; + yoffset = - customfunc(0,customparams); + end + if numFunc>1 + if j==1 + yyaxis left + elseif j==2 + yyaxis right + end + end + argj = arg.(name); + if isequal(name,'C') && ~isempty(regexp(Cspace,'isotropic*')) + xscale = ps.k0; + else + xscale = 1; + end + if numFunc==1 + ax.ColorOrderIndex = j; + end + if isequal(name,'mu') && ps.muderiv + [~,yarg] = modelfunc.(name)(argj*xscale); + else + yarg = modelfunc.(name)(argj*xscale); + end + plot(argj,yarg,ps.targetLineStyle,'LineWidth',2); + ylimtemp = ax.YLim; + hold on; + if numFunc==1 + ax.ColorOrderIndex = j; + end + if isequal(name,'mu') && ps.muderiv + [~,yarg] = customfunc(argj*xscale,customparams); + else + yarg = customfunc(argj*xscale,customparams)+yoffset; + end + plot(argj,yarg,'-','LineWidth',2); + if isempty(ps.yyaxisLim) + ax.YLim = ylimtemp; + else + ax.YLim = ps.yyaxisLim(j,:); + end + if ~isempty(ps.xlim) + ax.XLim = ps.xlim; + end + axis square + if ~isequal(ps.xlabel,'on') + ax.XTick = []; + else + if namesflag(1) && ~namesflag(2) + xl = '\eta'; + elseif ~namesflag(1) && namesflag(2) + xl = 'k/k_0'; + elseif all(namesflag) + xl = '\eta or k/k_0'; + end + xlabel(xl); + if ~isempty(ps.legend) + legend(ps.legend{:}); + legend('boxoff'); + end + end + end + if ps.label && j==1 && ~isempty(ind) + text(0.1,1.2,['Iter. ',num2str(ind-1)],'Units','normalized','HorizontalAlignment',ps.labelHorizontalAlignment); + end + end diff --git a/solver/history_movie.m b/solver/history_movie.m new file mode 100644 index 0000000..0c3fde4 --- /dev/null +++ b/solver/history_movie.m @@ -0,0 +1,234 @@ +function history_movie(resultpath,vid,ind,modelfunc,arg,tdata,ydata,params,kernelSize,Cspace, varargin) +%based on history_movie in CHACR/IP and history_production in RD/solver , produce a movie. +%must create a figure outside and a movie writer outside and pass the video object (vid) +%below are instructions from history_production, which may or may not be relevant here +%Two figures for figure handle +%note that ind is the indices of the optimization steps to be plotted. ind can also be 'end', in order to quickly visualize the final result. +%Use name value pair; +%'label'=true (default) to label the iteration number somewhere according to 'labelPosition'(= 'best' by default) for the first figure and to the left of each row for the second figure +%'labelxpos', coordinate of the x position of the label +%'labelHorizontalAlignment', 'left' (default), 'center','right' +%'ExchangeCurrentFieldColorScale', +%FrameIndex: selectively plot frames of c field by their index. ':' by default, meaning plotting all frames. +%Orientation: horizontal (default) arranges iterations (specified by ind) horizontally and different functions vertically; vertical does the other way +%yyaxisLim: each row corresponds to the ylim of each curve +%columntotal and rowtotal, overwrite the total number of columns and rows +%If there is more than one functions to plot, modelfunc should be a struct, whose field names match those in the meta. If there is only one function to plot, modelfunc can either be a struct or simply a function handle +%the result file can also contain y, the solution to the PDE at each step, in which case we don't need to recompute +%vararagout{1} is the all the subplots handles in 2D array form +ps = inputParser; +addParameter(ps,'funclabel',false); %label for functions +addParameter(ps,'funcxlabel',true); %xlabel for functions +addParameter(ps,'label',true); %label for iteration +addParameter(ps,'labelPosition','top'); +addParameter(ps,'labelpos',[0,1.2]); +addParameter(ps,'labelHorizontalAlignment','left'); +addParameter(ps,'ExchangeCurrentFieldColorScale',[]); +addParameter(ps,'FrameIndex',':'); +addParameter(ps,'Orientation','horizontal'); +addParameter(ps,'yyaxisLim',[]); +addParameter(ps,'timeLabel',true); %time is shifted such that t for the first frame is 0 +addParameter(ps,'timeLabelManual',[]); %replace the default time label above, must be a cell of char arrays +addParameter(ps,'FontSize',12); +addParameter(ps,'scale',[]); +addParameter(ps,'targetLineStyle','--'); +addParameter(ps,'title',[]); %left aligned, on top of the first data row +addParameter(ps,'stparg',{0.05,[0.1,0.08],0.05}); %argument for subtightplot +addParameter(ps,'visualizeArgs',{}); %additional arguments for visualize +addParameter(ps,'color',linspecer(2)); %color for lines +addParameter(ps,'save',true); %whether to save the ymodel result in resultpath +addParameter(ps,'use_saved',true); %whether to use saved ymodel result in resultpath +addParameter(ps,'darkmode',true); %generate darkmode movies +addParameter(ps,'offset',true); %if both C and mu are optimized. Whether to offset C with a constant term and offset mu with a the linear term +addParameter(ps,'muderiv',false); %plot mu'(c) instead of mu +addParameter(ps,'component',[]); %specify what functions to plot and in what order, only two allowed +addParameter(ps,'IP_DDFT_arg',{}); +addParameter(ps,'k0',1); %used to scale k +addParameter(ps,'dmu_at_0',1); %when meta has both mu and C, rescale so that dmu/dx at 0 has this value +addParameter(ps,'mu_at_0',0); %offset mu so that mu at 0 has this value + +parse(ps,varargin{:}); +ps = ps.Results; + +varload = matfile(resultpath); +history = varload.history; +has_y = ~isempty(who(varload,'y')); + +if isempty(ind) + ind = 1:size(history,1); +end + +%plot target and fitted function +if isempty(ps.component) + names = fieldnames(modelfunc); + names = names(1:2); + names = flip(sort(names)); +else + names = ps.component; +end +numFunc = numel(names); +numIter = length(ind); + + +frameindex = ps.FrameIndex; +if isequal(frameindex,':') + column = size(ydata,1); + frameindex = 1:column; +else + column = length(frameindex); +end +columntotal = column + 1; +rowtotal = 2; + +frameindex_model = frameindex; + +stparg = ps.stparg; + +clim = [min(min(ydata(frameindex,:))),max(max(ydata(frameindex,:)))]; + +hdata = visualize([],[],[],ydata(frameindex,:),'c',false,'ImageSize',params.N,'caxis',clim,'GridSize',[1,NaN],'OuterGridSize',[rowtotal,1],'OuterSubplot',[1,1],'ColumnTotal',columntotal,'StarterInd',1,'subtightplot',stparg,ps.visualizeArgs{:}); +data_cm = hdata(1).Colormap; + +if has_y && ps.use_saved + y = varload.y; +else + y = {}; +end + +open(vid); +for i = 1:numIter + if has_y && ps.use_saved + ymodel = y{ind(i)}; + [~,~,~,pp] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],history(ind(i),:),'mode','pp',ps.IP_DDFT_arg{:}); + else + [ymodel,~,~,pp] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],history(ind(i),:),'mode','eval',ps.IP_DDFT_arg{:}); + if ps.save + y{ind(i)} = ymodel; + end + end + hmodel = visualize([],[],[],ymodel(frameindex_model,:),'c',false,'ImageSize',params.N,'caxis',clim,'GridSize',[1,NaN],'OuterGridSize',[rowtotal,1],'OuterSubplot',[1,1],'ColumnTotal',columntotal,'StarterInd',columntotal+1,'subtightplot',stparg,ps.visualizeArgs{:}); + if all(ismember({'mu','C'},names)) && ps.offset + %calculate current gradient of mu at x=0 + grad0 = customizeFunGrad(pp.params,'mu','grad',0); + %gradient of the first order basis function of mu + [~,grad1] = feval(pp.params.mu.func,0,1); + %set the gradient of mu at x=0 to be 1. The offset is + offset = (ps.dmu_at_0-grad0)/grad1; + pp.params.mu.params(1) = pp.params.mu.params(1) + offset; + else + offset = 0; + end + + for j=1:numFunc + hfunc(j) = subtightplot(rowtotal,columntotal,(j-1)*columntotal+1,stparg{:}); + name = names{j}; + if isequal(name,'C') && ~isempty(regexp(Cspace,'isotropic*')) + customfunc = pp.params.Cfunc.func; + customparams = pp.params.Cfunc.params; + yoffset = offset; + elseif isequal(name,'mu') + customfunc = pp.params.(name).func; + customparams = pp.params.(name).params; + yoffset = - customfunc(0,customparams); + end + argj = arg.(name); + if isequal(name,'C') && ~isempty(regexp(Cspace,'isotropic*')) + xscale = ps.k0; + else + xscale = 1; + end + if isequal(name,'mu') && ps.muderiv + [~,yarg] = modelfunc.(name)(argj*xscale); + else + yarg = modelfunc.(name)(argj*xscale); + end + plot(argj,yarg,ps.targetLineStyle,'LineWidth',2,'Color',ps.color(j,:)); + ax = gca; + ylimtemp = ax.YLim; + hold on; + if isequal(name,'mu') && ps.muderiv + [~,yarg] = customfunc(argj*xscale,customparams); + else + yarg = customfunc(argj*xscale,customparams)+yoffset; + end + plot(argj,yarg,'-','LineWidth',2,'Color',ps.color(j,:)); + if isempty(ps.yyaxisLim) + ax.YLim = ylimtemp; + elseif all(isfinite(ps.yyaxisLim(j,:))) + ax.YLim = ps.yyaxisLim(j,:); + end + axis square + switch name + case 'mu' + ax.XTick = []; + clb = colorbar('southoutside','Position',[ax.Position(1),ax.Position(2)+0.04,ax.Position(3),0.03],'LineWidth',1); + if ps.darkmode + clb.Color = [1,1,1]; + end + case 'C' + if ps.funcxlabel + xlabel('k/k_0'); + end + end + if ps.darkmode + ax.Color = [0,0,0]; + ax.XColor = [1,1,1]; + ax.YColor = [1,1,1]; + end + ax.Colormap = data_cm; + if ps.funclabel + switch name + case 'mu' + if ps.muderiv + lab = "\mu_h'(c)"; + else + lab = '\mu_h(c)'; + end + case 'C' + lab = 'C_2(k)'; + end + tx = title(lab,'FontWeight','normal'); + if ps.darkmode + tx.Color = [1,1,1]; + end + end + end + if ps.label + tx = text(hfunc(1),ps.labelpos(1),ps.labelpos(2),['Iteration ',num2str(ind(i)-1)],'Units','normalized','HorizontalAlignment',ps.labelHorizontalAlignment); + if ps.darkmode + tx.Color = [1,1,1]; + end + end + set(findall(gcf,'-property','FontName'),'FontName','Arial'); + set(findall(gcf,'-property','FontWeight'),'FontWeight','normal'); + set(findall(gcf,'-property','FontSize'),'FontSize',ps.FontSize); + F = print('-RGBImage'); + writeVideo(vid,F); + delete(hfunc); + delete(hmodel); + if ps.label + delete(tx); + end +end +close(vid); + +if ps.save + varload.Properties.Writable = true; + varload.y = y; +end + +end + +function hOut = TextLocation(textString,varargin) + +l = legend(textString,varargin{:}); +t = annotation('textbox'); +t.String = textString; +t.Position = l.Position; +delete(l); +% t.LineStyle = 'None'; + +if nargout + hOut = t; +end +end diff --git a/solver/history_production.m b/solver/history_production.m new file mode 100644 index 0000000..53f3155 --- /dev/null +++ b/solver/history_production.m @@ -0,0 +1,165 @@ +function history_production(resultpath,ind,modelfunc,arg,tdata,ydata,params,kernelSize,Cspace,varargin) +%modelfunc and arg should both be struct with fieldnames corresponding to the parameters to be plotted +%note that ind is the indices of the optimization steps to be plotted. ind can also be 'end', in order to quickly visualize the final result. +%Use name value pair; +%'label'=true (default) to label the iteration number somewhere according to 'labelPosition'(= 'best' by default) for the first figure and to the left of each row for the second figure +%'labelxpos', coordinate of the x position of the label +%'labelHorizontalAlignment', 'left' (default), 'center','right' +%'ExchangeCurrentFieldColorScale', +%FrameIndex: selectively plot frames of c field by their index. ':' by default, meaning plotting all frames. +%Orientation: horizontal (default) arranges iterations (specified by ind) horizontally and different functions vertically; vertical does the other way +%yyaxisLim: each row corresponds to the ylim of each curve +%use CtruthSubplot as a vector to specify where to put the Ctruth +%If there is more than one functions to plot, modelfunc should be a struct, whose field names match those in the meta. If there is only one function to plot, modelfunc can either be a struct or simply a function handle +%the result file can also contain y, the solution to the PDE at each step, in which case we don't need to recompute +%IP_DDFT_arg, varargin for IP_DDFT +addpath('../../CHACR') +addpath('../../CHACR/IP') +ps = inputParser; +addParameter(ps,'xlabel','on'); +addParameter(ps,'label',true); +addParameter(ps,'labelPosition','top'); +addParameter(ps,'labelxpos',0.1); +addParameter(ps,'labelHorizontalAlignment','left'); +addParameter(ps,'ExchangeCurrentFieldColorScale',[]); +addParameter(ps,'FrameIndex',':'); +addParameter(ps,'Orientation','horizontal'); +addParameter(ps,'yyaxisLim',[]); +addParameter(ps,'xlim',[]); +addParameter(ps,'timeLabel',true); +addParameter(ps,'FontSize',12); +addParameter(ps,'legend',[]); +addParameter(ps,'scale',[]); +addParameter(ps,'CtruthSubplot',[]); +addParameter(ps,'IP_DDFT_arg',{}); +addParameter(ps,'k0',1); %used to scale k +addParameter(ps,'dmu_at_0',1); %when meta has both mu and C, rescale so that dmu/dx at 0 has this value +addParameter(ps,'mu_at_0',0); %offset mu so that mu at 0 has this value +addParameter(ps,'targetLineStyle','-.'); +addParameter(ps,'offset',true); %if both C and mu are optimized. Whether to offset C with a constant term and offset mu with a the linear term +addParameter(ps,'muderiv',false); %plot mu'(c) instead of mu +addParameter(ps,'showModelSolution',true); %plot the model solution at each iteration +addParameter(ps,'stparg',{0.05,[0.05,0.08],0.05}); %argument for subtightplot +parse(ps,varargin{:}); +ps = ps.Results; + +varload = matfile(resultpath); +history = varload.history; +savey = isempty(who(varload,'y')); +if savey + varload.Properties.Writable = true; +end +if isempty(ind) + ind = 1:size(history,1); +elseif isequal(ind,'end') + ind = size(history,1); +end + + +numIter = length(ind); +if isempty(ps.scale) + ps.scale = false(1,numIter); +end + +frameindex = ps.FrameIndex; +if isequal(frameindex,':') + column = size(ydata,1); + frameindex = 1:column; +else + column = length(frameindex); +end +if ps.showModelSolution + rowtotal = numIter+1; + columntotal = column; + frameindex_model = frameindex; + frameindex_model(frameindex==1) = []; %remove the initial condition +else + rowtotal = ceil(numIter/column) + 1; + columntotal = column; +end + +% 'color',[0.8500,0.3250,0.0980] +stparg = ps.stparg; +figure; +clim = [min(min(ydata(frameindex,:))),max(max(ydata(frameindex,:)))]; +h = visualize([],[],[],ydata(frameindex,:),'c',false,'ImageSize',params.N,'caxis',clim,'GridSize',[1,NaN],'OuterGridSize',[rowtotal,1],'OuterSubplot',[1,1],'ColumnTotal',columntotal,'StarterInd',0,'subtightplot',stparg); +if ps.timeLabel + for j = 1:length(h) + title(h(j),['t = ',num2str(tdata(frameindex(j)),2)]); + end + axes(h(1)); + text(0.1,1.5,'Data','Units','normalized','HorizontalAlignment',ps.labelHorizontalAlignment); +end + +if savey + y = {}; +else + y = varload.y; +end + +for i = 1:numIter + if ~ps.showModelSolution || (ps.showModelSolution && ~savey) + [~,~,~,pp] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],history(ind(i),:),'mode','pp',ps.IP_DDFT_arg{:}); + end + if ps.showModelSolution + if ~savey + y = varload.y; + visualize([],[],[],y{ind(i)}(frameindex_model,:),'c',false,'ImageSize',params.N,'caxis',clim,'GridSize',[1,NaN],'OuterGridSize',[rowtotal,1],'OuterSubplot',[i+1,1],'ColumnTotal',columntotal,'StarterInd',i*columntotal+1,'subtightplot',stparg); + else + [yhistory,~,~,pp] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],history(ind(i),:),'mode','eval',ps.IP_DDFT_arg{:}); + y{ind(i)} = yhistory; + visualize([],[],[],yhistory(frameindex_model,:),'c',false,'ImageSize',params.N,'caxis',clim,'GridSize',[1,NaN],'OuterGridSize',[rowtotal,1],'OuterSubplot',[i+1,1],'ColumnTotal',columntotal,'StarterInd',i*columntotal+1,'subtightplot',stparg); + end + ax = subtightplot(rowtotal,columntotal,i*columntotal+1,stparg{:}); + else + ax = subtightplot(rowtotal,columntotal,columntotal+i,stparg{:}); + end + + + if (ps.showModelSolution && i==numIter) || (~ps.showModelSolution && i==1) + ps.xlabel = 'on'; + else + ps.xlabel = []; + end + + history_func(ind(i),modelfunc,arg,Cspace,pp,ps); + +end + +if ismember(Cspace,{'k','real'}) && ~isempty(ps.CtruthSubplot) + axC = subtightplot(rowtotal,columntotal,columntotal*(ps.CtruthSubplot(1)-1)+ps.CtruthSubplot(2),stparg{:}); + CC = params.C; + halfSize = (kernelSize-1)/2; + CC((2+halfSize(1)):(end-halfSize(1)),:)=[]; + CC(:,(2+halfSize(2)):(end-halfSize(2)))=[]; + imagesc(fftshift(CC)); + axis(axC,'image'); + axC.XTick = []; + axC.YTick = []; + axC.Box = 'off'; + title('C_2 (truth)') + colormap(gca,'default') +end +set(findall(gcf,'-property','FontName'),'FontName','Arial'); +set(findall(gcf,'-property','FontWeight'),'FontWeight','normal'); +set(findall(gcf,'-property','FontSize'),'FontSize',ps.FontSize); + +if savey + varload.y = y; +end + +end + +function hOut = TextLocation(textString,varargin) + +l = legend(textString,varargin{:}); +t = annotation('textbox'); +t.String = textString; +t.Position = l.Position; +delete(l); +% t.LineStyle = 'None'; + +if nargout + hOut = t; +end +end diff --git a/solver/k2real.m b/solver/k2real.m new file mode 100644 index 0000000..2bbb41f --- /dev/null +++ b/solver/k2real.m @@ -0,0 +1,107 @@ +function varargout = k2real(y,N,y00,varargin) + %convert from k space to real space + %y comes in as a column vector, each column represent different snapshots Nt + %N is an array for the system size + %y00 is the k=0 component if missing in y, and must have the size of (1-Nt) + %mode: plot (default): show static snapshots; movie; value: calculate the y value in real space, returned in the same format + %caxis: 'auto' (default): each snapshot has its own automatic caxis; 'max': the caxis that accomondates the maximum and minimum of all the snapshots (only works for mode='plot'); 'first': all snapshots follow the min and max of the first snapshot; 'last': all snapshots follow the min and max of the last snapshot; a scalar, all snapshots follow the min and max of the snapshot numbered by the scalar; otherwise, all snapshots' clim specified by what's given. + Nt = size(y,2); + defaultcolumn = max(factor(Nt)); + defaultrow = Nt/defaultcolumn; + if length(y) == prod(N)-1 + if nargin<3 || isempty(y00) + y00 = zeros(1,Nt); + elseif isscalar(y00) + y00 = y00*ones(1,Nt); + end + y = [y00;y]; + end + ps = inputParser; + addParameter(ps,'mode','plot'); + addParameter(ps,'caxis','auto'); + addParameter(ps,'colorbar','off'); + addParameter(ps,'GridSize',[defaultrow,defaultcolumn]); + ps.KeepUnmatched = true; + parse(ps,varargin{:}); + params = ps.Results; + row = params.GridSize(1); + column = params.GridSize(2); + + if isscalar(params.caxis) + yreal = real(ifftn(reshape(y(:,params.caxis),N))); + yreal = yreal(:); + clim = [min(yreal),max(yreal)]; + else + switch params.caxis + case 'max' + clim = 'auto'; + case 'first' + yreal = real(ifftn(reshape(y(:,1),N))); + yreal = yreal(:); + clim = [min(yreal),max(yreal)]; + case 'last' + yreal = real(ifftn(reshape(y(:,end),N))); + yreal = yreal(:); + clim = [min(yreal),max(yreal)]; + otherwise + clim = params.caxis; + end + end + + switch params.mode + case 'plot' + vis = 1; + case 'movie' + vis = 2; + F(Nt) = struct('cdata',[],'colormap',[]); + case 'value' + vis = 0; + end + for i=1:Nt + yreal = real(ifftn(reshape(y(:,i),N))); + if vis == 1 + h(i) = subplot(row,column,i); + imagesc(yreal); + axis(h(i),'equal','tight'); + colormap(h(i),'gray'); + caxis(h(i),clim); + elseif vis == 2 + h = imagesc(yreal); + axis(gca,'equal','tight'); + colormap(gca,'gray'); + caxis(gca,clim); + F(i) = getframe(gcf); + delete(h); + else + y(:,i) = yreal(:); + end + ax = gca; + ax.XTick=[]; ax.YTick=[]; + if isequal(params.colorbar,'on') + colorbar; + else + colorbar(params.colorbar); + end + end + if isequal(params.caxis,'max') && vis == 1 + for i=1:Nt + climi = h(i).CLim; + if i==1 + clim = climi; + else + clim(1) = min(clim(1),climi(1)); + clim(2) = max(clim(2),climi(2)); + end + end + for i=1:Nt + caxis(h(i),clim); + end + end + if vis == 1 + varargout = {h}; + elseif vis == 2 + varargout = {F}; + else + varargout = {y}; + end +end diff --git a/solver/machta.m b/solver/machta.m new file mode 100644 index 0000000..d30ebbe --- /dev/null +++ b/solver/machta.m @@ -0,0 +1,21 @@ +n = 7; +theta = ones(1,n)/n; + +ntime = n; +rholen = n^2; +theta = padarray(theta,[0,(rholen-n)/2],0,'both'); +n = rholen; +center = ceil(rholen/2); +rho = zeros(ntime,rholen); +drho = zeros(ntime,rholen,n); +hessian_t = zeros(n,n,ntime); +rho(1,center) = 1; +for i = 2:ntime + rho(i,:) = conv(rho(i-1,:),theta,'same'); + for j = 1:n + drho(i,:,j) = conv(drho(i-1,:,j),theta,'same') + circshift(rho(i-1,:),j); + end + drho_t = squeeze(drho(i,:,:)); + hessian_t(:,:,i) = drho_t' * drho_t; +end +[V,D] = eig(hessian_t(:,:,end)); diff --git a/solver/mainFig.m b/solver/mainFig.m new file mode 100644 index 0000000..a9fcf3d --- /dev/null +++ b/solver/mainFig.m @@ -0,0 +1,147 @@ +%the script for the main figure for DDFT +addpath('../../CHACR/GIP') + +L = [5,5]; +N = [256,256]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 10; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +if ~exist('t2','var') + [t1,y1,params] = solver_DDFT([],[],params); + + xx = linspace(0,L(1),N(1)); + yy = linspace(0,L(2),N(2)); + [xx,yy] = ndgrid(xx,yy); + center = L/2; + radius = 0.06*L(1); + thickness = 0.01*L(1); + roi = roi_circle(xx,yy,center,radius,thickness); + + %nucleus + y0 = y1(end,:)'; + roi = roi(:); + y02 = 0.045; + rho = (y02*n - sum(roi.*y0)) / sum(1-roi); + y0 = roi.*y0 + (1-roi)*rho; + + tspan2 = linspace(0,2.5,100); + [t2,y2] = solver_DDFT(tspan2,y0,params); + + ind = 1:20:100; + tdata = t2(ind); + ydata = y2(ind,:); +end + +rowtotal = 4; +columntotal = 5; +stparg = {0.05,[0.08,0.06],[0.07,0.03]}; +clim = [min(min(ydata(:))),max(max(ydata(:)))]; +figure; +%first row: data +h = visualize([],[],[],ydata,'c',false,'ImageSize',params.N,'caxis',clim,'GridSize',[1,NaN],'OuterGridSize',[rowtotal,1],'OuterSubplot',[1,1],'subtightplot',stparg); +for j = 1:length(h) + title(h(j),['t = ',num2str(tdata(j),2)]); + h(j).Position(2) = h(j).Position(2) + 0.02; +end +axes(h(1)); +text(0.01,1.46,'(a) Data','Units','normalized','HorizontalAlignment','left'); +%second row: history of DDFT_nucleation23 +kernelSize = 2; +Cspace = 'isotropic'; +params.moreoptions = moreodeset('gmresTol',1e-5); +IP_DDFT_arg = {'Nmu',3}; +figprop = {'IP_DDFT_arg',IP_DDFT_arg,'yyaxisLim',[-0.5,1.5;-1,1.2],'k0',k0,'xlim',[min(ydata(:)),2]}; +resultpath = [largedatapath,'DDFT_nucleation23']; +varload = load(resultpath); +history = varload.history; +modelfunc.C = @(k) exp(-(k-k0).^2/(2*alpha^2))*0.95; +modelfunc.mu = @(x) x - x.^2/2 + x.^3/3; +arg.C = linspace(0,2,500); +arg.mu = linspace(min(ydata(:)),max(ydata(:)),100); +ind = [1,19,25,31,1797]; +for i = 1:length(ind) + ax = subtightplot(rowtotal,columntotal,columntotal+i,stparg{:}); + ax.Position(2) = ax.Position(2) + 0.025; + [~,~,~,pp] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],history(ind(i),:),'mode','pp',IP_DDFT_arg{:}); + history_func(ind(i),modelfunc,arg,Cspace,pp,[],figprop{:}); + if i~=1 + xlabel([]); + yyaxis left + yticklabels([]); + yyaxis right + yticklabels([]); + else + text(0.01,1.53,'(b) Quartic approximation','Units','normalized','HorizontalAlignment','left'); + legend({'$\hat{C_2}(k)$ (truth)','$\hat{C_2}(k)$','$\mu_h(\eta)$ (truth)','$\mu_h(\eta)$'},... + 'Orientation','horizontal','Position',[0.10 0 0.8169 0.0374],'Interpreter','latex'); + legend('boxoff'); + end +end +%third row: final result of DDFT_nucleation23 +if ~exist('yhistory','var') + [yhistory,~,~,pp] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],history(end,:),'mode','eval',IP_DDFT_arg{:}); +end +%highlight the difference between model and data in the last image +Ntime = size(yhistory,1); +for i = 1:Ntime + h(i) = subtightplot(rowtotal,columntotal,columntotal*2+i,stparg{:}); + if i >= Ntime - 1 + C = imfuse(mat2gray(reshape(yhistory(i,:),params.N),flip(clim)),mat2gray(reshape(ydata(i,:),params.N),flip(clim)),'Scaling','none'); + C = mydecorrstretch(C,[1,0.2,0.2]); + imshow(C); + else + imshow(mat2gray(reshape(yhistory(i,:),params.N),flip(clim))); + end +end +%show all model plots (without difference) +% h = visualize([],[],[],yhistory,'c',false,'ImageSize',params.N,'caxis',clim,'GridSize',[1,NaN],'OuterGridSize',[rowtotal,1],'OuterSubplot',[3,1],'subtightplot',stparg); +%show difference between model and data only +% h = visualize([],[],[],yhistory-ydata,'c',false,'ImageSize',params.N,'caxis','auto','GridSize',[1,NaN],'OuterGridSize',[rowtotal,1],'OuterSubplot',[3,1],'subtightplot',stparg); +for i = 1:length(h) + h(i).Position(2) = h(i).Position(2) - 0; +end +text(h(1),0.01,1.2,'(c) Quartic approximation result','Units','normalized','HorizontalAlignment','left'); + +%fourth row: history of DDFT_nucleation30 +kernelSize = 10; +Cspace = 'isotropic_hermite_scale'; +Crange = [0,4]; +IP_DDFT_arg = {'Nmu',0,'discrete',true,'cutoff',k0}; +figprop = {'IP_DDFT_arg',IP_DDFT_arg,'yyaxisLim',[-0.5,1.2],'k0',k0,'xlim',Crange}; +resultpath = [largedatapath,'DDFT_nucleation30']; +varload = load(resultpath); +history = varload.history; +arg.C = linspace(Crange(1),Crange(2),500); +ind = [1,11,16,21,36]; +%the following is used on MIT laptop +ind = [1,4,11,26,35]; +for i = 1:length(ind) + ax = subtightplot(rowtotal,columntotal,columntotal*3+i,stparg{:}); + ax.Position(2) = ax.Position(2) + 0.01; + if i==length(ind) + DDFT_nucleation36; + delete(hl); + hold on; + end + [~,~,~,pp] = IP_DDFT(tdata,ydata,params,kernelSize,Cspace,[],history(ind(i),:),'mode','pp',IP_DDFT_arg{:}); + history_func(ind(i),modelfunc,arg,Cspace,pp,[],figprop{:}); + if i~=1 + xlabel([]); + yticklabels([]); + else + text(0.01,1.54,'(d) Hermite function basis function','Units','normalized','HorizontalAlignment','left'); + end +end +f = gcf; +set(findall(f,'-property','FontName'),'FontName','Arial'); +set(findall(f,'-property','FontWeight'),'FontWeight','normal'); +set(findall(f,'-property','FontSize'),'FontSize',13); +f.Position = [680 321 588 657]; +% print(f,'C:\Users\zhbkl\Dropbox (MIT)\Research\Report 6\figure\DDFT_mainFig','-dtiff','-r400'); diff --git a/solver/moreodeget.m b/solver/moreodeget.m new file mode 100644 index 0000000..6ca29cd --- /dev/null +++ b/solver/moreodeget.m @@ -0,0 +1,119 @@ +function o = moreodeget(options,name,default,flag) + % used for moreoptions in myode15s +%ODEGET Get ODE OPTIONS parameters. +% VAL = ODEGET(OPTIONS,'NAME') extracts the value of the named property +% from integrator options structure OPTIONS, returning an empty matrix if +% the property value is not specified in OPTIONS. It is sufficient to type +% only the leading characters that uniquely identify the property. Case is +% ignored for property names. [] is a valid OPTIONS argument. +% +% VAL = ODEGET(OPTIONS,'NAME',DEFAULT) extracts the named property as +% above, but returns VAL = DEFAULT if the named property is not specified +% in OPTIONS. For example +% +% val = odeget(opts,'RelTol',1e-4); +% +% returns val = 1e-4 if the RelTol property is not specified in opts. +% +% See also ODESET, ODE45, ODE23, ODE113, ODE15S, ODE23S, ODE23T, ODE23TB. + +% Mark W. Reichelt and Lawrence F. Shampine, 3/1/94 +% Copyright 1984-2016 The MathWorks, Inc. + +% undocumented usage for fast access with no error checking +if (nargin == 4) && isequal(char(flag),'fast') + o = getknownfield(options,name,default); + return +end + +if nargin < 2 + error(message('MATLAB:odeget:NotEnoughInputs')); +end +if nargin < 3 + default = []; +end +if isstring(name) && isscalar(name) + name = char(name); +end +if ~isempty(options) && ~isa(options,'struct') + error(message('MATLAB:odeget:Arg1NotODESETstruct')); +end + +if isempty(options) + o = default; + return; +end + +Names = [ + 'blockLU ' + 'blockLUadj ' + 'blockIter ' + 'blockIterLead ' + 'blockIterStaticInd ' + 'blockIterStaticJac ' + 'ErrorControl ' + 'FSA ' + 'FSAerror ' + 'gmresmaxit ' + 'gmresTol ' + 'imex ' + 'interpFcn ' + 'jacMult ' + 'Krylov ' + 'KrylovDecomp ' + 'KrylovPrecon ' + 'linear ' + 'linearMult ' + 'maxit ' + 'pencil ' + 'restart ' + 'sensFcn ' + 'skipInit ' + 'updateJ ' % backward compatibility + 'youtSel ' + 'ysutSel ' + 'ys0 ' + 'ysp0 ' + ]; + +names = lower(Names); + +lowName = lower(name); +j = strmatch(lowName,names); +if isempty(j) % if no matches + error(message('MATLAB:odeget:InvalidPropName', name)); +elseif length(j) > 1 % if more than one match + % Check for any exact matches (in case any names are subsets of others) + k = strmatch(lowName,names,'exact'); + if length(k) == 1 + j = k; + else + matches = deblank(Names(j(1),:)); + for k = j(2:length(j))' + matches = [matches ', ' deblank(Names(k,:))]; %#ok + end + error(message('MATLAB:odeget:AmbiguousPropName',name,matches)); + end +end + +if any(strcmp(fieldnames(options),deblank(Names(j,:)))) + o = options.(deblank(Names(j,:))); + if isempty(o) + o = default; + end +else + o = default; +end + +% -------------------------------------------------------------------------- +function v = getknownfield(s, f, d) +%GETKNOWNFIELD Get field f from struct s, or else yield default d. + +if isfield(s,f) % s could be empty. + v = s.(f); + if isempty(v) + v = d; + end +else + v = d; +end diff --git a/solver/moreodeset.m b/solver/moreodeset.m new file mode 100644 index 0000000..6c839f3 --- /dev/null +++ b/solver/moreodeset.m @@ -0,0 +1,273 @@ +function options = moreodeset(varargin) +% used for moreoptions in myode15s +%ODESET Create/alter ODE OPTIONS structure. +% OPTIONS = ODESET('NAME1',VALUE1,'NAME2',VALUE2,...) creates an integrator +% options structure OPTIONS in which the named properties have the +% specified values. Any unspecified properties have default values. It is +% sufficient to type only the leading characters that uniquely identify the +% property. Case is ignored for property names. +% +% OPTIONS = ODESET(OLDOPTS,'NAME1',VALUE1,...) alters an existing options +% structure OLDOPTS. +% +% OPTIONS = ODESET(OLDOPTS,NEWOPTS) combines an existing options structure +% OLDOPTS with a new options structure NEWOPTS. Any new properties +% overwrite corresponding old properties. +% +% ODESET with no input arguments displays all property names and their +% possible values. +% +%ODESET PROPERTIES +% +%RelTol - Relative error tolerance [ positive scalar {1e-3} ] +% This scalar applies to all components of the solution vector, and +% defaults to 1e-3 (0.1% accuracy) in all solvers. The estimated error in +% each integration step satisfies e(i) <= max(RelTol*abs(y(i)),AbsTol(i)). +% +%AbsTol - Absolute error tolerance [ positive scalar or vector {1e-6} ] +% A scalar tolerance applies to all components of the solution vector. +% Elements of a vector of tolerances apply to corresponding components of +% the solution vector. AbsTol defaults to 1e-6 in all solvers. See RelTol. +% +%NormControl - Control error relative to norm of solution [ on | {off} ] +% Set this property 'on' to request that the solvers control the error in +% each integration step with norm(e) <= max(RelTol*norm(y),AbsTol). By +% default the solvers use a more stringent component-wise error control. +% +%Refine - Output refinement factor [ positive integer ] +% This property increases the number of output points by the specified +% factor producing smoother output. Refine defaults to 1 in all solvers +% except ODE45, where it is 4. Refine does not apply if length(TSPAN) > 2 +% or the ODE solver returns the solution as a structure. +% +%OutputFcn - Installable output function [ function_handle ] +% This output function is called by the solver after each time step. When +% a solver is called with no output arguments, OutputFcn defaults to +% @odeplot. Otherwise, OutputFcn defaults to []. +% +%OutputSel - Output selection indices [ vector of integers ] +% This vector of indices specifies which components of the solution vector +% are passed to the OutputFcn. OutputSel defaults to all components. +% +%Stats - Display computational cost statistics [ on | {off} ] +% +%Jacobian - Jacobian function [ function_handle | constant matrix ] +% Set this property to @FJac if FJac(t,y) returns dF/dy, or to +% the constant value of dF/dy. +% For ODE15I solving F(t,y,y') = 0, set this property to @FJac if +% [dFdy, dFdyp] = FJac(t,y,yp), or to a cell array of constant +% values {dF/dy,dF/dyp}. +% +%JPattern - Jacobian sparsity pattern [ sparse matrix ] +% Set this property to a sparse matrix S with S(i,j) = 1 if component i of +% F(t,y) depends on component j of y, and 0 otherwise. +% For ODE15I solving F(t,y,y') = 0, set this property to +% {dFdyPattern,dFdypPattern}, the sparsity patterns of dF/dy and +% dF/dy', respectively. +% +%Vectorized - Vectorized ODE function [ on | {off} ] +% Set this property 'on' if the ODE function F is coded so that +% F(t,[y1 y2 ...]) returns [F(t,y1) F(t,y2) ...]. +% For ODE15I solving F(t,y,y') = 0, set this property to +% {yVect,ypVect}. Setting yVect 'on' indicates that +% F(t,[y1 y2 ...],yp) returns [F(t,y1,yp) F(t,y2,yp) ...]. +% Setting ypVect 'on' indicates that F(t,y,[yp1 yp2 ...]) +% returns [F(t,y,yp1) F(t,y,yp2) ...]. +% +%Events - Locate events [ function_handle ] +% To detect events, set this property to the event function. +% +%Mass - Mass matrix [ constant matrix | function_handle ] +% For problems M*y' = f(t,y) set this property to the value of the constant +% mass matrix. For problems with time- or state-dependent mass matrices, +% set this property to a function that evaluates the mass matrix. +% +%MStateDependence - Dependence of the mass matrix on y [ none | {weak} | strong ] +% Set this property to 'none' for problems M(t)*y' = F(t,y). Both 'weak' and +% 'strong' indicate M(t,y), but 'weak' will result in implicit solvers +% using approximations when solving algebraic equations. +% +%MassSingular - Mass matrix is singular [ yes | no | {maybe} ] +% Set this property to 'no' if the mass matrix is not singular. +% +%MvPattern - dMv/dy sparsity pattern [ sparse matrix ] +% Set this property to a sparse matrix S with S(i,j) = 1 if for any k, the +% (i,k) component of M(t,y) depends on component j of y, and 0 otherwise. +% +%InitialSlope - Consistent initial slope yp0 [ vector ] +% yp0 satisfies M(t0,y0)*yp0 = F(t0,y0). +% +%InitialStep - Suggested initial step size [ positive scalar ] +% The solver will try this first. By default the solvers determine an +% initial step size automatically. +% +%MaxStep - Upper bound on step size [ positive scalar ] +% MaxStep defaults to one-tenth of the tspan interval in all solvers. +% +%NonNegative - Non-negative solution components [ vector of integers ] +% This vector of indices specifies which components of the +% solution vector must be non-negative. NonNegative defaults to []. +% This property is not available in ODE23S, ODE15I. In ODE15S, +% ODE23T, and ODE23TB, the property is not available for problems +% where there is a mass matrix. +% +%BDF - Use Backward Differentiation Formulas in ODE15S [ on | {off} ] +% This property specifies whether the Backward Differentiation Formulas +% (Gear's methods) are to be used in ODE15S instead of the default +% Numerical Differentiation Formulas. +% +%MaxOrder - Maximum order of ODE15S and ODE15I [ 1 | 2 | 3 | 4 | {5} ] +% +% See also ODEGET, ODE45, ODE23, ODE113, ODE15I, ODE15S, ODE23S, ODE23T, ODE23TB, +% FUNCTION_HANDLE. + +% Mark W. Reichelt and Lawrence F. Shampine, 5/6/94 +% Copyright 1984-2016 The MathWorks, Inc. + +% Print out possible values of properties. +if (nargin == 0) && (nargout == 0) + fprintf(' blockLU: [ {false} | true ]\n'); + fprintf(' blockLUadj: [ {false} | true ]\n'); + fprintf(' blockIter: [ {false} | true ]\n'); + fprintf(' blockIterLead: [ {Dynamic} | Static | Jacobi ]\n'); + fprintf(' blockIterStaticInd: [ {[]} | integer array ]\n'); + fprintf(' blockIterStaticJac: [ {[]} | struct ]\n'); + fprintf(' ErrorControl: [ {1:neq} | array ]\n'); + fprintf(' FSA: [ {false} | true ]\n'); + fprintf(' FSAerror: [ {false} | true ]\n'); + fprintf(' gmresmaxit: [ {5} | positive integer ]\n'); + fprintf(' gmresTol: [ {0.005} | positive ]\n'); + fprintf(' imex: [ {false} | true ]\n'); + fprintf(' interpFcn: [ {[]} | function handle ]\n'); + fprintf(' jacMult: [ {[]} | function handle ]\n'); + fprintf(' Krylov: [ {false} | true ]\n'); + fprintf(' KrylovDecomp: [ {[]} | function handle ]\n'); + fprintf(' KrylovPrecon: [ {[]} | function handle ]\n'); + fprintf(' linear: [ {false} | true ]\n'); + fprintf(' linearMult: [ {[]} | function handle ]\n'); + fprintf(' maxit: [ {4 ~blockIter, 10 blockIter} | integer ]\n'); + fprintf(' pencil: [ {[]} | function handle ]\n'); + fprintf(' restart: [ {5} | positive integer ]\n'); + fprintf(' sensFcn: [ {[]} | function handle ]\n'); + fprintf(' skipInit: [ {false} | true ]\n'); + fprintf(' updateJ: [ {false} | true ]\n'); + fprintf(' youtSel: [ {[]} | positive integer array ]\n'); + fprintf(' ysoutSel: [ {[]} | positive integer array ]\n'); + fprintf(' ys0: [ {[]} | array ]\n'); + fprintf(' ysp0: [ {[]} | array ]\n'); + fprintf('\n'); + return; +end + +Names = [ + 'blockLU ' + 'blockLUadj ' + 'blockIter ' + 'blockIterLead ' + 'blockIterStaticInd ' + 'blockIterStaticJac ' + 'ErrorControl ' + 'FSA ' + 'FSAerror ' + 'gmresmaxit ' + 'gmresTol ' + 'imex ' + 'interpFcn ' + 'jacMult ' + 'Krylov ' + 'KrylovDecomp ' + 'KrylovPrecon ' + 'linear ' + 'linearMult ' + 'maxit ' + 'pencil ' + 'restart ' + 'sensFcn ' + 'skipInit ' + 'updateJ ' % backward compatibility + 'youtSel ' + 'ysoutSel ' + 'ys0 ' + 'ysp0 ' + ]; +m = size(Names,1); +names = lower(Names); + +% Combine all leading options structures o1, o2, ... in odeset(o1,o2,...). +options = []; +for j = 1:m + options.(deblank(Names(j,:))) = []; +end +i = 1; +while i <= nargin + arg = varargin{i}; + if ischar(arg) || (isstring(arg) && isscalar(arg)) % arg is an option name + break; + end + if ~isempty(arg) % [] is a valid options argument + if ~isa(arg,'struct') + error(message('MATLAB:odeset:NoPropNameOrStruct', i)); + end + for j = 1:m + if any(strcmp(fieldnames(arg),deblank(Names(j,:)))) + val = arg.(deblank(Names(j,:))); + else + val = []; + end + if ~isempty(val) + options.(deblank(Names(j,:))) = val; + end + end + end + i = i + 1; +end +% Convert string arguments and options. +for ii = 1:nargin + if isstring(varargin{ii}) && isscalar(varargin{ii}) + varargin{ii} = char(varargin{ii}); + end +end + +% A finite state machine to parse name-value pairs. +if rem(nargin-i+1,2) ~= 0 + error(message('MATLAB:odeset:ArgNameValueMismatch')); +end +expectval = 0; % start expecting a name, not a value +while i <= nargin + arg = varargin{i}; + + if ~expectval + if ~ischar(arg) + error(message('MATLAB:odeset:NoPropName', i)); + end + + lowArg = lower(arg); + j = strmatch(lowArg,names); + if isempty(j) % if no matches + error(message('MATLAB:odeset:InvalidPropName', arg)); + elseif length(j) > 1 % if more than one match + % Check for any exact matches (in case any names are subsets of others) + k = strmatch(lowArg,names,'exact'); + if length(k) == 1 + j = k; + else + matches = deblank(Names(j(1),:)); + for k = j(2:length(j))' + matches = [matches ', ' deblank(Names(k,:))]; %#ok + end + error(message('MATLAB:odeset:AmbiguousPropName',arg,matches)); + end + end + expectval = 1; % we expect a value next + + else + options.(deblank(Names(j,:))) = arg; + expectval = 0; + + end + i = i + 1; +end + +if expectval + error(message('MATLAB:odeset:NoValueForProp', arg)); +end diff --git a/solver/mydecorrstretch.m b/solver/mydecorrstretch.m new file mode 100644 index 0000000..f274c31 --- /dev/null +++ b/solver/mydecorrstretch.m @@ -0,0 +1,197 @@ +function S = mydecorrstretch(A, relativeStretch, useCorr) +%use relative stretch (a three-valued array) to specify the magnitude of stretching in each principle components +if nargin < 2 + relativeStretch = ones(3,1); +end +if nargin < 3 + useCorr = true; +end +% Decorrelation stretch for a multiband image of class double. +inputClass = class(A); +if ~strcmp(inputClass,'double') + A = im2double(A); +end + +[r c nbands] = size(A); % Save the shape +npixels = r * c; % Number of pixels +A = reshape(A,[npixels nbands]); % Reshape to numPixels-by-numBands +B = A; + +meanB = mean(B,1); % Mean pixel value in each spectral band +targetMean = meanB; + +n = size(B,1); % Equals npixels if rowsubs is empty +if n == 1 + cov = zeros(nbands); +else + cov = (B' * B - (n * meanB') * meanB)/(n - 1); % Sample covariance matrix +end + +[T, offset] = fitdecorrtrans(meanB, cov, useCorr, targetMean, [], relativeStretch); + +S = bsxfun(@plus, A*T, offset); +S = reshape(S, [r c nbands]); + +S = images.internal.changeClass(inputClass,S); +end + +function [T, offset] = fitdecorrtrans(means, Cov, useCorr, targetMean, targetSigma, relativeStretch) +% FITDECORRTRANS Fit decorrelating transformation to image statistics. +% +% Given MEANS, a 1-by-NBANDS vector of band means, and COV, an NBANDS-by-NBANDS +% band covariance matrix, calculate an NBANDS-by-NBANDS linear transformation +% matrix, T, and 1-by-NBANDS offset vector, OFFSET, that will decorrelate +% an image with those statistics. If A is such an image, reshaped to size +% NPIXELS-by-NBANDS, then A is decorrelated as follows: +% +% A * T + repmat(OFFSET,[NPIXELS 1]). +% +% Set USECORR=true to use the correlation matrix to derive T, or set +% USECORR=false to use the covariance matrix. T is scaled to either (1) +% achieve the target standard deviation specified by TARGETSIGMA (either +% a scalar or an NBANDS-by-NBANDS diagonal matrix) or (2), if TARGETSIGMA=[], +% to preserve the variances on the diagonal of COV. Likewise, OFFSET +% includes a shift to either (1) set the mean of each output band to +% a specified target (TARGETMEAN, either a scalar or a 1-by-NBANDS vector) +% or (2), if TARGETMEAN=[], to preserve the band-means specified in MEANS. +% +% It's easy to verify that FITDECORRTRANS has worked by checking that +% +% T' * Cov * T +% +% equals diag(COV), TARGETSIGMA^2, or TARGETSIGMA^2 * eye(NBANDS). +% Likewise, one can check that +% +% means * T + OFFSET +% +% equals either MEANS or TARGETMEANS. +% +% Even in the case of perfectly or nearly correlated bands, FITDECORRTRANS +% remains stable. T and OFFSET continue to provide a reasonable-looking +% result when applied to an image with the appropriate statistics. However, +% +% T' * Cov * T +% +% will no longer be diagonal, and its diagonal elements corresponding to +% zero-variance bands will be zero. +% +% Notes +% ----- +% In general, T is not unique, because once an image has been decorrelated +% (via left multiplication by T = V * inv(sqrt(D)) * V') it can be +% rotated arbitrarily in band space without reintroducing correlations. +% All these different choices will give the same value of T' * Cov * T. +% +% The correlation and covariance methods each produce a different, but +% valid T. Those particular choices for T also have the desirable property +% of preserving, roughly, the hue of a given pixel. +% +% The correlation method may be understood as follows. Consider the image +% that is derived by scaling the original image, band by band, to have +% unit variance in each band. The correlation matrix of the original +% image is the covariance matrix of this derived image. That is, +% if S is a diagonal matrix containing the square-root band-variances, +% of image A, then Corr is the covariance of A / S (assuming that A has +% been reshaped to size NPIXELS-by-NBANDS). Thus the expression +% below, T = pinv(S) * V * decorrWeight(D) * V' * targetSigma, can be +% understood as follows when applied to A step by step: +% +% Scale A band-wise to achieve unit variance in each band: +% A * pinv(S) +% +% Transform the scaled A to the eigenvector basis: +% A * pinv(S) * V +% +% Decorrelate: +% A * pinv(S) * V * decorrWeight(D) +% +% Transform back (resulting in unit variance in each band): +% A * pinv(S) * V * decorrWeight(D) * V' +% +% Scale each band to achieve the desired standard deviation: +% A * pinv(S) * V * decorrWeight(D) * V' * targetSigma +% +% (The covariance method works the same, but because there's no need for an +% initial scaling to unit variance the pinv(S) factor is omitted.) +% +% Robustness is achieved by: +% 1. Ensuring that the correlation matrix has ones on the diagonal +% (even in the event of one or more uniform bands) +% 2. Through the use of PINV in place of INV +% 3. By forcing any small negative eigenvalues to zero +% 4. By rescaling T as needed to compensate for the +% effects of a rank-deficient covariance matrix. +% +% References +% ---------- +% +% Alley, Ronald E., Algorithm Theoretical Basis Document for Decorrelation +% Stretch, Version 2.2, Jet Propulsion Laboratory, Pasadena, CA, +% August 15,1996. +% +% Mather, Paul M., Computer Processing of Remotely-Sensed Images: An +% Introduction, 2nd Edition, John Wiley & Sons, 1999. + +% Copyright 2002 The MathWorks, Inc. + +% Square-root variances in a diagonal matrix. +S = diag(sqrt(diag(Cov))); + +if isempty(targetSigma) + % Restore original sample variances. + targetSigma = S; +end + +if useCorr + Corr = pinv(S) * Cov * pinv(S); + Corr(logical(eye(size(Corr,1)))) = 1; + [V D] = eig(Corr); + T = pinv(S) * V * decorrWeight(D, relativeStretch) * V' * targetSigma; +else + [V D] = eig(Cov); + T = V * decorrWeight(D, relativeStretch) * V' * targetSigma; +end + +% Get the output variances right even for correlated bands, except +% for zero-variance bands---which can't be stretched at all. +T = T * pinv(diag(sqrt(diag(T' * Cov * T)))) * targetSigma; + +if isempty(targetMean) + % Restore original sample means. + targetMean = means; +end + +offset = targetMean - means * T; +end + +%-------------------------------------------------------------------------- +function W = decorrWeight(D, relativeStretch) + +% Given the diagonal eigenvalue matrix D, compute the decorrelating +% weights W. In the full rank, well-conditioned case, decorrWeight(D) +% returns the same result as sqrt(inv(D)). In addition, it provides +% a graceful way to handle rank-deficient or near-rank-deficient +% (ill-conditioned) cases resulting from situations of perfect or +% near-perfect band-to-band correlation and/or bands with zero variance. + +D(D < 0) = 0; +W = sqrt(pinv(D)) .* diag(relativeStretch); +end + +%-------------------------------------------------------------------------- +function S = pinv(D) + +% Pseudoinverse of a diagonal matrix, with a larger-than-standard +% tolerance to help in handling edge cases. We've provided our +% own in order to: (1) Avoid replacing all calls to PINV with calls to +% PINV(...,TOL) and (2) Take advantage of the fact that our input is +% always diagonal so we don't need to call SVD. + +d = diag(D); +tol =length(d) * max(d) * sqrt(eps); +keep = d > tol; +s = ones(size(d)); +s(keep) = s(keep) ./ d(keep); +s(~keep) = 0; +S = diag(s); +end diff --git a/solver/ntrp15s.m b/solver/ntrp15s.m new file mode 100644 index 0000000..3276524 --- /dev/null +++ b/solver/ntrp15s.m @@ -0,0 +1,64 @@ +function [yinterp,ypinterp] = ntrp15s(tinterp,~,~,tnew,ynew,h,dif,k,idxNonNegative) +%NTRP15S Interpolation helper function for ODE15S. +% YINTERP = NTRP15S(TINTERP,T,Y,TNEW,YNEW,H,DIF,K,IDX) uses data computed in +% ODE15S to approximate the solution at time TINTERP. TINTREP may be a +% scalar or a row vector. +% The arguments T and Y do not affect the computations. They are required +% for consistency of syntax with other interpolation functions. Any values +% entered for T and Y are ignored. +% +% [YINTERP,YPINTERP] = NTRP15S(TINTERP,T,Y,TNEW,YNEW,H,DIF,K,IDX) returns +% also the derivative of the polynomial approximating the solution. +% +% IDX has indices of solution components that must be non-negative. Negative +% YINTERP(IDX) are replaced with zeros and the derivative YPINTERP(IDX) is +% set to zero. +% +% See also ODE15S, DEVAL. + +% Mark W. Reichelt and Lawrence F. Shampine, 6-13-94 +% Copyright 1984-2009 The MathWorks, Inc. + +s = (tinterp - tnew)/h; + +ypinterp = []; +if k == 1 + yinterp = ynew(:,ones(size(tinterp))) + dif(:,1) * s; + if nargout > 1 + hdif = (1/h)*dif(:,1); + ypinterp = hdif(:,ones(size(tinterp))); + end +else % cumprod collapses vectors + K = (1:k)'; + kI = K(:,ones(size(tinterp))); + yinterp = ynew(:,ones(size(tinterp))) + ... + dif(:,K) * cumprod((s(ones(k,1),:)+kI-1)./kI); + + if nargout > 1 + ypinterp = dif(:,ones(size(tinterp))); + S = ones(size(tinterp)); + dS = ones(size(tinterp)); + for i=2:k + S = S .* (i-2+s)/i; + dS = dS .* (i-1+s)/i + S; + ypinterp = ypinterp + dif(:,i)*dS; + end + ypinterp = ypinterp/h; + end + +end + +% Non-negative solution +if ~isempty(idxNonNegative) + idx = find(yinterp(idxNonNegative,:)<0); % vectorized + if ~isempty(idx) + w = yinterp(idxNonNegative,:); + w(idx) = 0; + yinterp(idxNonNegative,:) = w; + if nargout > 1 % the derivative + w = ypinterp(idxNonNegative,:); + w(idx) = 0; + ypinterp(idxNonNegative,:) = w; + end + end +end diff --git a/solver/odeimex.m b/solver/odeimex.m new file mode 100644 index 0000000..87c8d21 --- /dev/null +++ b/solver/odeimex.m @@ -0,0 +1,578 @@ +function varargout = odeimex(fnlin,J,tspan,y0,options,pencil,moreoptions,JexMult,exsensFcn,dJdp) +%a simplified ode solver adapted from ode15s +%the backward diffusion / NDF is applied for the linear part of the equation, in particular, the propotionality constant is J, note that J can be an array the same as y0 (equivalent to diagonal), in this case, the mass matrix must be diagonal as well. Alternatively, J can be a matrix, in which case pencil is needed. +%The nonlinear part of the equation is explicit, that is, at each time step, this term is dependent only on the previous time step. +%only ODE (not DAE) is supported right now. +%dy/dt = J*y + fnlin +%Nt is the number of time steps +%the format of yout is different from typical ode, each column corresponds to a time point given in tout, which is a column vector. +%pencil(b,hinvGak) should return (Mt-hinvGak*J)\b +%right now J is constant +%the mass matrix Mt is also constant +%JexMult is the multiplying function for the jacobian of the explicit term (argument: ys, t, y) +%exsensFcn is the sensitivity of the explicit term +%dJdp is the sensitivity of the multiplying matrix of the implicit term + + +if nargin<5 + options = []; +end +if nargin<7 + moreoptions = []; +end +%output +FcnHandlesUsed = true; +haveInterpFcn = false; +output_sol = (FcnHandlesUsed && (nargout==1) && ~haveInterpFcn); % sol = odeXX(...) +output_ty = (~output_sol && (nargout > 0) && ~haveInterpFcn); % [t,y,...] = odeXX(...) +sol = []; kvec = []; dif3d = []; difs4d = []; +if output_sol + sol.solver = solver_name; + sol.extdata.odefun = ode; + sol.extdata.options = options; + sol.extdata.varargin = varargin; +end + +maxk = odeget(options,'MaxOrder',5,'fast'); +bdf = strcmp(odeget(options,'BDF','off','fast'),'on'); +htry = abs(odeget(options,'InitialStep',[],'fast')); +hmax = abs(odeget(options,'MaxStep',inf,'fast')); +rtol = odeget(options,'RelTol',1e-3,'fast'); +atol = odeget(options,'AbsTol',1e-6,'fast'); +Mt = odeget(options,'Mass',[],'fast'); +normcontrol = strcmp(odeget(options,'NormControl','off','fast'),'on'); +%copied from odearguments +htspan = abs(tspan(2) - tspan(1)); +tspan = tspan(:); +ntspan = length(tspan); +t0 = tspan(1); +next = 2; % next entry in tspan +tfinal = tspan(end); +tdir = sign(tfinal - t0); +refine = max(1,odeget(options,'Refine',1,'fast')); +if ntspan > 2 + outputAt = 'RequestedPoints'; % output only at tspan points +elseif refine <= 1 + outputAt = 'SolverSteps'; % computed points, no refinement +else + outputAt = 'RefinedSteps'; % computed points, with refinement + S = (1:refine-1) / refine; +end +idxNonNegative = []; + +%Forward sensitivity analysis +FSA = moreodeget(moreoptions,'FSA',false,'fast'); +FSAerror = moreodeget(moreoptions,'FSAerror',false,'fast'); +ys = moreodeget(moreoptions,'ys0',[],'fast'); +ysp = moreodeget(moreoptions,'ysp0',[],'fast'); +if isempty(ys) || isempty(ysp) + FSA = false; +end +interpFcn = moreodeget(moreoptions,'interpFcn',[],'fast'); +haveInterpFcn = ~isempty(interpFcn); +%usage: initialize if flag = 'init', while all the other arguments are empty. At the end of each time step taken by the solver, the input to interpFcn is flag = '',info,tnew,ynew,h,dif,k,idxNonNegative, everything needed to do interpolationm the output of interpFcn is info. Note that info is passed from one time step to another and is the output of myode15s varargout. When successfully finalizing, the flag is 'done', when the solver fails, the flag is 'fail', both with the same inputs as before. +%note that if haveInterpFcn, the output will be the output of interpFcn when flag is done, no t, or y or sol wil be outputted! + +neq = length(y0); +ninst = size(ys,2); +if isempty(Mt) + Mt = speye(neq); +end + +threshold = atol / rtol; +if normcontrol + normy = norm(y0); + if FSA + normys = vecnorm(ys); + end +end + +t = t0; +y = y0; + +vectorJ = all(size(J)==size(y)); +if vectorJ + yp = fnlin(t,y) + J.*y; + Mtdiag = full(diag(Mt)); +else + yp = fnlin(t,y) + J*y; +end + +% Initialize method parameters. +G = [1; 3/2; 11/6; 25/12; 137/60]; +if bdf + alpha = [0; 0; 0; 0; 0]; +else + alpha = [-37/200; -1/9; -0.0823; -0.0415; 0]; +end +invGa = 1 ./ (G .* (1 - alpha)); +erconst = alpha .* G + (1 ./ (2:6)'); +G3(1,1,:) = G; % for FSA +difU = [ -1, -2, -3, -4, -5; % difU is its own inverse! + 0, 1, 3, 6, 10; + 0, 0, -1, -4, -10; + 0, 0, 0, 1, 5; + 0, 0, 0, 0, -1 ]; +maxK = 1:maxk; +[kJ,kI] = meshgrid(maxK,maxK); +difU = difU(maxK,maxK); + +% Determine initial step size + +% hmin is a small number such that t + hmin is clearly different from t in +% the working precision, but with this definition, it is 0 if t = 0. +hmin = 16*eps*abs(t); + +if isempty(htry) + % Compute an initial step size h using yp = y'(t). + if normcontrol + wt = max(normy,threshold); + rh = 1.25 * (norm(yp) / wt) / sqrt(rtol); % 1.25 = 1 / 0.8 + else + wt = max(abs(y),threshold); + rh = 1.25 * norm(yp ./ wt,inf) / sqrt(rtol); + end + absh = hmax; + if absh * rh > 1 + absh = 1 / rh; + end + absh = max(absh, hmin); +else + absh = min(hmax, max(hmin, htry)); +end +h = tdir * absh; + +% Initialize. +k = 1; % start at order 1 with BDF1 +K = 1; % K = 1:k +klast = k; +abshlast = absh; +abshFSA = absh; %record the absh and k at previous FSA stepping +kFSA = k; + +dif = zeros(neq,maxk+2); +dif(:,1) = h * yp; +if FSA + difs = zeros(neq,ninst,maxk+2); + difs(:,:,1) = h * ysp; +end + +hinvGak = h * invGa(k); +nconhk = 0; % steps taken with current h and k + +% Allocate memory if we're generating output. +nout = 0; +tout = []; yout = []; +ysout = []; +if nargout > 0 + if output_sol + chunk = min(max(100,50*refine), refine+floor((2^11)/neq)); + tout = zeros(1,chunk); + yout = zeros(neq,chunk); + kvec = zeros(1,chunk); + dif3d = zeros(neq,maxk+2,chunk); + if FSA + ysout = zeros(neqsout,ninst,chunk); + difs4d = zeros(neqsout,ninst,maxk+2,chunk); + end + else + if ntspan > 2 % output only at tspan points + tout = zeros(1,ntspan); + yout = zeros(neq,ntspan); + if FSA + ysout = zeros(neqsout,ninst,ntspan); + end + else % alloc in chunks + chunk = min(max(100,50*refine), refine+floor((2^13)/neq)); + tout = zeros(1,chunk); + yout = zeros(neq,chunk); + if FSA + ysout = zeros(neqsout,ninst,chunk); + end + end + end + nout = 1; + tout(nout) = t; + yout(:,nout) = y; + if FSA + ysout(:,:,nout) = ys; + end +end + +if haveInterpFcn + interp_info = feval(interpFcn,'init',[],[],[],[],[],[],[]); +end + +% THE MAIN LOOP + +done = false; +at_hmin = false; +while ~done + + hmin = 16*eps(t); + absh = min(hmax, max(hmin, absh)); + if absh == hmin + if at_hmin + absh = abshlast; % required by stepsize recovery + end + at_hmin = true; + else + at_hmin = false; + end + h = tdir * absh; + + % Stretch the step if within 10% of tfinal-t. + if 1.1*absh >= abs(tfinal - t) + h = tfinal - t; + absh = abs(h); + done = true; + end + + if (absh ~= abshlast) || (k ~= klast) + difRU = cumprod((kI - 1 - kJ*(absh/abshlast)) ./ kI) * difU; + dif(:,K) = dif(:,K) * difRU(K,K); + + hinvGak = h * invGa(k); + nconhk = 0; + + end + + % LOOP FOR ADVANCING ONE STEP. + nofailed = true; % no failed attempts + fex = fnlin(t,y); % the nonlinear part is fixed in the iteration + while true % Evaluate the formula. + + % Compute the constant terms in the equation for ynew. + psi = dif(:,K) * (G(K) * invGa(k)); + + % Predict a solution at t+h. + tnew = t + h; + if done + tnew = tfinal; % Hit end point exactly. + end + h = tnew - t; % Purify h. + pred = y + sum(dif(:,K),2); + ynew = pred; + + if normcontrol + normynew = norm(ynew); + invwt = 1 / max(max(normy,normynew),threshold); + else + invwt = 1 ./ max(max(abs(y),abs(ynew)),threshold); + end + + rhs = Mt*(ynew-psi) + hinvGak*fex; + if vectorJ + ynew2 = rhs ./ (Mtdiag - hinvGak*J); + else + ynew2 = pencil(rhs,hinvGak); + end + + difkp1 = ynew2-ynew; + ynew = ynew2; + + % difkp1 is now the backward difference of ynew of order k+1. + if normcontrol + err = (norm(difkp1) * invwt) * erconst(k); + else + err = norm(difkp1 .* invwt,inf) * erconst(k); + end + + fail = (err > rtol); + + if ~fail && FSA %successful, move on to FSA + if abshFSA ~= absh || kFSA ~= k + difRU = cumprod((kI - 1 - kJ*(absh/abshFSA)) ./ kI) * difU; + difRU4d = permute(difRU(K,K),[3,4,1,2]); + difs(:,:,K) = squeeze(sum(difs(:,:,K) .* difRU4d, 3)); + abshFSA = absh; + kFSA = k; + end + %time step is already known + %the following is fixed since time step is fixed and so is difs + psis = sum(difs(:,:,K) .* G3(1,1,K),3) * invGa(k); + preds = ys + sum(difs(:,:,K),3); + ynews = preds; + if normcontrol + normynews = vecnorm(ynews); + invwts = 1 ./ max(max(normys,normynews),threshold); + else + invwts = 1 ./ max(max(abs(ys),abs(ynews)),threshold); + end + + dfexdy = feval(Jex,t,y); + sensval= feval(exsensFcn,t,y); + fs = dfexdy*ys + (dJdp*ynew + sensval); + rhss = Mt*(ynews-psis) + hinvGak*fs; + if vectorJ + ynews2 = rhss ./ (Mtdiag - hinvGak*J); + else + ynews2 = pencil(rhss,hinvGak); + end + difkp1s = ynews2-ynews; + ynews = ynews2; + + if FSAerror + if normcontrol + errs = (vecnorm(difkp1s) .* invwts) * erconst(k); + else + errs = vecnorm(difkp1s .* invwts,inf) * erconst(k); + end + err = max(err,max(errs)); + if err > rtol + fail = true; + end + end + end + + if fail + if absh <= hmin + warning(message('MATLAB:ode15s:IntegrationTolNotMet', sprintf( '%e', t ), sprintf( '%e', hmin ))); + if haveInterpFcn + interp_info = feval(interpFcn,'fail',interp_info,tnew,ynew,h,dif,k,idxNonNegative); + varargout = interp_info; + return; + end + solver_output = odefinalize_ez(sol,nout,tout,yout,kvec,dif3d,difs4d,idxNonNegative,ysout); + if nargout > 0 + varargout = solver_output; + end + return; + end + + abshlast = absh; + if nofailed + nofailed = false; + hopt = absh * max(0.1, 0.833*(rtol/err)^(1/(k+1))); % 1/1.2 + if k > 1 + if normcontrol + errkm1 = (norm(dif(:,k) + difkp1) * invwt) * erconst(k-1); + else + errkm1 = norm((dif(:,k) + difkp1) .* invwt,inf) * erconst(k-1); + end + hkm1 = absh * max(0.1, 0.769*(rtol/errkm1)^(1/k)); % 1/1.3 + if hkm1 > hopt + hopt = min(absh,hkm1); % don't allow step size increase + k = k - 1; + K = 1:k; + end + end + absh = max(hmin, hopt); + else + absh = max(hmin, 0.5 * absh); + end + h = tdir * absh; + + difRU = cumprod((kI - 1 - kJ*(absh/abshlast)) ./ kI) * difU; + dif(:,K) = dif(:,K) * difRU(K,K); + + hinvGak = h * invGa(k); + nconhk = 0; + + else % Successful step + break; + + end + end % while true + + dif(:,k+2) = difkp1 - dif(:,k+1); + dif(:,k+1) = difkp1; + for j = k:-1:1 + dif(:,j) = dif(:,j) + dif(:,j+1); + end + + if output_sol + nout = nout + 1; + if nout > length(tout) + tout = [tout, zeros(1,chunk)]; % requires chunk >= refine + yout = [yout, zeros(neq,chunk)]; + kvec = [kvec, zeros(1,chunk)]; + dif3d = cat(3,dif3d, zeros(neq,maxk+2,chunk)); + if FSA + ysout = cat(3,ysout, zeros(neqsout,ninst,chunk)); + difs4d = cat(4,difs4d, zeros(neqsout,ninst,maxk+2,chunk)); + end + end + tout(nout) = tnew; + yout(:,nout) = ynew; + kvec(nout) = k; + dif3d(:,:,nout) = dif; + if FSA + ysout(:,:,nout) = ynews; + difs4d(:,:,:,nout) = difs; + end + end + + if output_ty || haveOutputFcn + switch outputAt + case 'SolverSteps' % computed points, no refinement + nout_new = 1; + tout_new = tnew; + yout_new = ynew; + if FSA + ysout_new = ynews; + end + case 'RefinedSteps' % computed points, with refinement + tref = t + (tnew-t)*S; + nout_new = refine; + tout_new = [tref, tnew]; + yout_new = [ntrp15s(tref,[],[],tnew,ynew,h,dif,k,idxNonNegative), ynew]; + if FSA + ysout_new = cat(3,ntrp15svec(tref,[],[],tnew,ynews,h,difs,k,idxNonNegative), ynews); + end + case 'RequestedPoints' % output only at tspan points + nout_new = 0; + tout_new = []; + yout_new = []; + ysout_new = []; + while next <= ntspan + if tdir * (tnew - tspan(next)) < 0 + break; + end + nout_new = nout_new + 1; + tout_new = [tout_new, tspan(next)]; + if tspan(next) == tnew + yout_new = [yout_new, ynew]; + if FSA + ysout_new = cat(3, ysout_new, ynews); + end + else + yout_new = [yout_new, ntrp15s(tspan(next),[],[],tnew,ynew,h,dif,k,... + idxNonNegative)]; + if FSA + ysout_new = cat(3, ysout_new, ntrp15svec(tspan(next),[],[],tnew,ynews,h,difs,k,... + idxNonNegative)); + end + end + next = next + 1; + end + end + + if nout_new > 0 + if output_ty + oldnout = nout; + nout = nout + nout_new; + if nout > length(tout) + tout = [tout, zeros(1,chunk)]; % requires chunk >= refine + yout = [yout, zeros(neq,chunk)]; + if FSA + ysout = cat(3, ysout, zeros(neqsout,ninst,chunk)); + end + end + idx = oldnout+1:nout; + tout(idx) = tout_new; + yout(:,idx) = yout_new; + if FSA + ysout(:,:,idx) = ysout_new; + end + end + end + end + + if haveInterpFcn + interp_info = feval(interpFcn,'',interp_info,tnew,ynew,h,dif,k,idxNonNegative); + end + + klast = k; + abshlast = absh; + nconhk = min(nconhk+1,maxk+2); + if nconhk >= k + 2 + temp = 1.2*(err/rtol)^(1/(k+1)); + if temp > 0.1 + hopt = absh / temp; + else + hopt = 10*absh; + end + kopt = k; + if k > 1 + if normcontrol + errkm1 = (norm(dif(:,k)) * invwt) * erconst(k-1); + else + errkm1 = norm(dif(:,k) .* invwt,inf) * erconst(k-1); + end + temp = 1.3*(errkm1/rtol)^(1/k); + if temp > 0.1 + hkm1 = absh / temp; + else + hkm1 = 10*absh; + end + if hkm1 > hopt + hopt = hkm1; + kopt = k - 1; + end + end + if k < maxk + if normcontrol + errkp1 = (norm(dif(:,k+2)) * invwt) * erconst(k+1); + else + errkp1 = norm(dif(:,k+2) .* invwt,inf) * erconst(k+1); + end + temp = 1.4*(errkp1/rtol)^(1/(k+2)); + if temp > 0.1 + hkp1 = absh / temp; + else + hkp1 = 10*absh; + end + if hkp1 > hopt + hopt = hkp1; + kopt = k + 1; + end + end + if hopt > absh + absh = hopt; + if k ~= kopt + k = kopt; + K = 1:k; + end + end + end + % Advance the integration one step. + t = tnew; + y = ynew; + if FSA + ys = ynews; + end + if normcontrol + normy = normynew; + if FSA + normys = normynews; + end + end +end + +if haveInterpFcn + interp_info = feval(interpFcn,'done',interp_info,tnew,ynew,h,dif,k,idxNonNegative); + varargout = interp_info; + return; +end +solver_output = odefinalize_ez(sol,nout,tout,yout,kvec,dif3d,difs4d,idxNonNegative,ysout); +if nargout > 0 + varargout = solver_output; +end +end + + +function solver_output = odefinalize_ez(sol,nout,tout,yout,kvec,dif3d,difs4d,idxNonNegative,ysout) + solver_output = {}; + if (nout > 0) % produce output + if isempty(sol) % output [t,y,...] + solver_output{1} = tout(1:nout).'; + solver_output{2} = yout(:,1:nout); + if ~isempty(ysout) + solver_output{3} = permute(ysout(:,:,1:nout),[3,1,2]); + end + else % output sol + % Add remaining fields + sol.x = tout(1:nout); + sol.y = yout(:,1:nout); + sol.idata.kvec = kvec(1:nout); + maxkvec = max(sol.idata.kvec); + sol.idata.dif3d = dif3d(:,1:maxkvec+2,1:nout); + if ~isempty(difs4d) + sol.idata.difs4d = difs4d(:,:,1:maxkvec+2,1:nout); + end + sol.idata.idxNonNegative = idxNonNegative; + solver_output{1} = sol; + end + end +end diff --git a/solver/odeimexez.m b/solver/odeimexez.m new file mode 100644 index 0000000..2240479 --- /dev/null +++ b/solver/odeimexez.m @@ -0,0 +1,78 @@ +function [tout,yout,et] = odeimex(fnlin,J,h,Nt,y0,pencil,outputstep,termination,gpu,transform) +%easy version odeimex: fixed time step, no error control +%h: step size +%outputstep: an array that indicates at which step the solution is outputed (must be sorted). By default, it only returns the last step +%termination: a function handle (t,y,yp) that returns true or a nonzero value when the solver should abort the iteration. The output et is true or the corresponding value when it's terminated early. By default, termination is empty +%when the solver terminates, the last column of yout is the y at the time step of termination, the unfilled yout is removed. Similarly for tout +%y is the value at the latest time point, yp is the estimated time derivative (y-yold)/dt +%the output yout is stored on gpu if gpu is true. For now, tout is always stored on cpu. By default, gpu is set to false. +%transform is a function handle that transforms the output y (by default empty) +%04/11/2019, now J can be a matrix or a column vector whose size is the same as y +%pencil(b,hinvGak) should return (Mt-hinvGak*J)\b +%right now J is constant +neq = length(y0); +y = y0; +t = 0:h:(h*Nt); +if nargin < 7 || isempty(outputstep) + outputstep = Nt; +end +if nargin < 8 + termination = []; +end +if nargin < 9 || isempty(gpu) + gpu = false; +end +if nargin < 10 + transform = []; +end +tout = t(outputstep); +if gpu + yout = zeros(neq,length(outputstep),'gpuArray'); +else + yout = zeros(neq,length(outputstep)); +end +outputid = 1; +if outputstep(outputid) == 1 + if isempty(transform) + yout(:,outputid) = y; + else + yout(:,outputid) = transform(y); + end + outputid = outputid + 1; +end +et = false; + +vectorJ = all(size(J)==size(y)); + +for step = 2:Nt + yold = y; + fex = fnlin(t(step-1),y); % the nonlinear part is fixed in the iteration + if vectorJ + y = (y+h*fex)./(1-h*J); + else + y = pencil(y+h*fex,h); + end + if outputstep(outputid) == step + if isempty(transform) + yout(:,outputid) = y; + else + yout(:,outputid) = transform(y); + end + outputid = min(outputid+1,length(outputstep)); + end + if ~isempty(termination) + yp = (y-yold)/h; + et = termination(t(step),y,yp); + if et + if isempty(transform) + yout(:,outputid) = y; + else + yout(:,outputid) = transform(y); + end + yout(:,outputid+1:end) = []; + tout(:,outputid) = h*(step-1); + tout(:,outputid+1:end) = []; + break; + end + end +end diff --git a/solver/presentation_RD.m b/solver/presentation_RD.m new file mode 100644 index 0000000..b04efc7 --- /dev/null +++ b/solver/presentation_RD.m @@ -0,0 +1,39 @@ +%L = [5,5]; +%N = [1000,1000]; +L = [10,10]; +N = [2000,2000]; +%N = [256*2,256*2]; +%L = [2.5,10]; +%N = [500,2000]; +%L = [5,5]; +%N = [2000,2000]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 50; +%R_D5 +%k0 = 100; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + + +tspan = 0:0.1:5; +tspan = linspace(0,0.2,101); +params.options = odeset('OutputFcn',@(t,y,flag) simOutput(t,y,flag,true,[])); + +y0 = randomfield(N,L,'RBF',2*pi/k0/10,1); +y0 = y0(:); +y0 = []; +[t1,y1,params] = solver_DDFT(tspan,y0,params); + +y = permute(reshape(y1,[length(tspan),N]),[2,3,1]); + + +%save([largedatapath,'presentation_RD_4'],'y'); +% im = circshift(circshift(y(:,:,18),300,2),250,1); +% im = (im-min(im(:)))/(max(im(:))-min(im(:))); +% im = ind2rgb(floor(im*255),cmocean('thermal')); +% imwrite(im,'C:\Users\zhbkl\Dropbox (MIT)\Research\Report 6\figure\presentation_RD.png'); diff --git a/solver/presentation_RD_nucleus.m b/solver/presentation_RD_nucleus.m new file mode 100644 index 0000000..1d8fa24 --- /dev/null +++ b/solver/presentation_RD_nucleus.m @@ -0,0 +1,82 @@ +%based on presentation_RD and DDFT_nucleation, start from a nucleus +L = [5,5]; +N = [1024,1024]; +% L = [10,10]; +% N = [2000,2000]; +n = prod(N); + +params.N = N; +params.L = L; + +[k2,k] = formk(N,L); +k0 = 50; +alpha = 5; +params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; + +params.options = odeset('OutputFcn',@(t,y,flag) simOutput(t,y,flag,true,[])); + +tspan = linspace(0,0.2,3); + +y0 = []; +[t1,y1,params] = solver_DDFT(tspan,y0,params); + +y1 = y1(end,:); +y1 = reshape(y1,N); + +imcenter = y1((N(1)/2-50):(N(1)/2+50),(N(2)/2-50):(N(2)/2+50)); +imcenter = y1(1:101,1:101); +[ii,jj] = find(imcenter==max(imcenter(:))); +xx = 1:size(imcenter,1); +yy = 1:size(imcenter,2); +[xx,yy]=ndgrid(xx,yy); +%mask around the nucleus +mask = ((xx-ii).^2+(yy-jj).^2)<(pi/k0*N(1)/L(1))^2; +nucleus = imcenter .* mask; +ind1 = find(any(mask,2)); +ind2 = find(any(mask,1)); +nucleus = nucleus(ind1,ind2); +mask = mask(ind1,ind2); +shift = floor(size(mask)/2); +roi = zeros(N); +y0 = zeros(N); +xind = N(1)/2-shift(1)-1 + (1:size(mask,1)); +yind = N(2)/2-shift(2)-1 + (1:size(mask,2)); %indices for placing nucleus in the center +roi(xind,yind) = mask; +y0(xind,yind) = nucleus; + +%initial condition for the crystallization from a nuclues +y0 = y0(:); +roi = roi(:); +y02 = 0.08; +rho = (y02*n - sum(roi.*y0)) / sum(1-roi); +y0 = roi.*y0 + (1-roi)*rho; + +tspan = linspace(0,0.4,601); +[t2,y2,params] = solver_DDFT(tspan,y0,params); +y2 = permute(reshape(y2,[length(t2),N]),[2,3,1]); + +ysample = y2(:,:,1:60:end); +% imwrite((y2-min(y2(:)))/(max(y2(:))-min(y2(:))),[largedatapath,'presentation_RD_nucleus.png']); + +mv = VideoWriter([largedatapath,'presentation_RD_nucleus']); +open(mv); +writeVideo(mv,(permute(y2,[1,2,4,3])-min(y2(:)))/(max(y2(:))-min(y2(:)))); +close(mv); + +mv = VideoWriter([largedatapath,'presentation_RD_nucleus']); +open(mv); +yk = abs(fft2(y2)); +yk(1,1,:) = 0; +yk = fftshift(fftshift(yk,1),2); +Ncutoff = k0.*L/2/pi; +Ncutoff = floor(Ncutoff * 4); +yk = yk((N(1)/2-Ncutoff):(N(1)/2+Ncutoff),(N(2)/2-Ncutoff):(N(2)/2+Ncutoff),:); +writeVideo(mv,permute(min(yk./max(yk,[],[1,2])*10,1),[1,2,4,3])); +close(mv); + +%write the C2 function into an image +c=fftshift(ifft2(params.C)); +cl=linspecer(2); +cc=divergentColormap(cl(1,:),cl(2,:),c,true,max(c(:))*[-1,1],[0,0,0]); +alpha = abs(c)/max(abs(c(:))); +imwrite(cc,'C:\Users\zhbkl\Dropbox (MIT)\Research\Report 6\figure\presentation_RD_nucleus_C2.png','Alpha',alpha.^0.7); \ No newline at end of file diff --git a/solver/roi_circle.m b/solver/roi_circle.m new file mode 100644 index 0000000..d97e97f --- /dev/null +++ b/solver/roi_circle.m @@ -0,0 +1,30 @@ +function roi = roi_circle(xx,yy,center,radius,d,operation) + %a diffuse shape function for union and intersection of circles, whose centers (N*2) and radii (N*1 or 1*N) are listed as arrays. + %xx and yy can be 1D array in different directions or matrices of the same size + %d is the diffuse layer thickness, it can be a scalar or two element for x and y directions + %operation takes the roi of each circle as input and operate on it + %if operation is not provided, we take the union (sum) + N = size(center,1); + if isscalar(d) + d = d*ones(1,N); + end + union = (nargin < 6) || isempty(operation); + + for i = 1:N + r = sqrt((xx-center(i,1)).^2 + (yy-center(i,2)).^2); + roi_i = 1./(1 + exp((r - radius(i))/d(i))); + if union + if i == 1 + roi = roi_i; + else + roi = min((roi + roi_i),1); %union operator + end + else + roi_out{i} = roi_i; + end + end + + if ~union + roi = feval(operation,roi_out{:}); + end +end diff --git a/solver/roi_rectangle.m b/solver/roi_rectangle.m new file mode 100644 index 0000000..4767605 --- /dev/null +++ b/solver/roi_rectangle.m @@ -0,0 +1,23 @@ +function roi = roi_rectangle(xx,yy,xrange,yrange,d) + %a diffuse shape function for a rectangle, x > xrange(1), x < xrange(2), y > yrange(1), y < yrange(2) + %use Inf or NaN to indicate no bound + %xx and yy are arrays of the same size + %d is the diffuse layer thickness, it can be a scalar or two element for x and y directions + if isscalar(d) + d = [d,d]; + end + roi = ones(size(xx)); + for i = 1:2 + center = xrange(i); + if isfinite(center) + s = 2*i-3; + roi = roi.*(1./(1+exp(s*(xx-center)/d(1)))); + end + end + for i = 1:2 + center = yrange(i); + if isfinite(center) + s = 2*i-3; + roi = roi.*(1./(1+exp(s*(yy-center)/d(2)))); + end + end diff --git a/solver/runningcov.m b/solver/runningcov.m new file mode 100644 index 0000000..6c0770f --- /dev/null +++ b/solver/runningcov.m @@ -0,0 +1,15 @@ +function [sigma,runningdyad,runningsum] = runningcov(x,runningdyad,runningsum) + %x can be a row vector or a matrix whose columns represent instances + %The first output sigma is the accumulative covariance + persistent N + if nargin<3 + runningdyad = x'*x; + runningsum = sum(x,1); + N = size(x,1); + else + runningdyad = runningdyad + x'*x; + runningsum = runningsum + sum(x,1); + N = N+size(x,1); + end + sigma = (runningdyad - runningsum'*runningsum/N)/(N-1); +end diff --git a/solver/sens.m b/solver/sens.m new file mode 100644 index 0000000..d85c685 --- /dev/null +++ b/solver/sens.m @@ -0,0 +1,26 @@ +addpath('../../CHACR/GIP') +L = [5,5]; +N = [256,256]; +n = prod(N); +Nbasis = 1000; +t = 1; +[k2,k] = formk(N,L); +absk = sqrt(k2); +k0 = 10; +alpha = 5; +C = exp(-(absk-k0).^2/(2*alpha^2))*0.95; +y0 = 0.06; +dmu = (1-y0+y0^2); +sigma = - k2 .* (dmu - C); +psi = laguerrepoly(absk,Nbasis) .* exp(-absk/2); +deta = k2 .* exp(sigma*t) .* psi; +deta = reshape(deta,n,Nbasis); +hessian = deta' * deta; +[V,D] = eig(hessian); + +xx = linspace(0,20,1000)'; +figure; +for i = 1:3 + subplot(1,3,i); + plot(xx,laguerrepoly(xx,[],V(:,end-i+1)).*exp(-xx/2)); +end diff --git a/solver/sens1D.m b/solver/sens1D.m new file mode 100644 index 0000000..54d1ef0 --- /dev/null +++ b/solver/sens1D.m @@ -0,0 +1,32 @@ +addpath('../../CHACR/GIP') +Nbasis = 5000; +t = 1; +k = linspace(0,100,10000)'; +k2 = k.^2; +k0 = 10; +alpha = 5; +C = exp(-(k-k0).^2/(2*alpha^2))*0.95; +y0 = 0.06; +dmu = (1-y0+y0^2); +sigma = - k2 .* (dmu - C); + +bound = [k(1),k(end)]; +kscale = (k-mean(bound))/diff(bound); +psi = legendrepoly(kscale,Nbasis) .* sqrt(2*(1:Nbasis)-1); +% psi = laguerrepoly(k,Nbasis) .* exp(-k/2); +deta = k .* k2 .* exp(sigma*t) .* psi; +scale = (k .* k2 .* exp(sigma*t)).^2; +hessian = deta' * deta; +[V,D] = eig(hessian); + +xx = linspace(0,20,1000)'; +figure; +for i = 1:3 + subplot(1,3,i); + % plot(xx,laguerrepoly(xx,[],V(:,end-i+1)).*exp(-xx/2)); + % plot(k,psi*V(:,end-i+1)); + plot(xx,legendrepoly((xx-mean(bound))/diff(bound),[],V(:,end-i+1) .* sqrt(2*(1:Nbasis)-1)')); +end + +figure; +plot(k,psi*V(:,end)); \ No newline at end of file diff --git a/solver/solver_DDFT.m b/solver/solver_DDFT.m new file mode 100644 index 0000000..acd0406 --- /dev/null +++ b/solver/solver_DDFT.m @@ -0,0 +1,437 @@ +function varargout = solver_DDFT(tspan,y0,params,meta,mode,varargin) +%this provides solution to both forward and backward evaluation +%set mode = 'forward' (default) to perform model evaluation, in this mode, we accept two varargin, varargin{1} is sol, when true (false by default), output sol structure (varargin = {tout,sol,params},, when false, varargin = {tout,y,params}. varargin{2} is FSA, when true (false by default), also computes FSA and varargin{4} = ys. +%set mode = 'adjoint' to perform ASA analysis. varargin{1} = error, varargin{2] = discrete, tspan and y0 must be tdata and sol (solution history). varargout = {grad} +%params can also contain options and moreoptions +ASA = (nargin > 4) && isequal(mode,'adjoint'); +ps = inputParser; +addParameter(ps,'error',[]); +addParameter(ps,'discrete',[]); +addParameter(ps,'sol',false); +addParameter(ps,'FSA',false); +ps.CaseSensitive = false; +parse(ps,varargin{:}); +if ASA + error = ps.Results.error; + discrete = ps.Results.discrete; +else + sol = ps.Results.sol; + FSA = ps.Results.FSA; +end + +addpath('../../CHACR/odesolver') +%in order to be consistent with formk, the first dimension is x and the second dimension is y +if ~isfield(params,'dx') && isfield(params,'N') && isfield(params,'L') + params.dx = params.L ./ params.N; +elseif ~isfield(params,'N') && isfield(params,'dx') && isfield(params,'L') + params.N = params.L ./ params.dx; +elseif ~isfield(params,'L') && isfield(params,'N') && isfield(params,'dx') + params.L = params.N .* params.dx; +elseif ~all(isfield(params,{'dx','N','L'})) + params.N = [128,128]; + params.L = [5,5]; + params.dx = params.L./params.N; +end +n = prod(params.N); +N = params.N; +L = params.L; +dx = params.dx; +if ~isfield(params,'D') || isempty(params.D) + %here D is a constant diffusivity that sets the time scale + params.D = 1; +end +if ~isfield(params,'C') || isempty(params.C) + %default + [k2,k] = formk(N,L); + k0 = 10; + alpha = 2; + params.C = exp(-(sqrt(k2)-k0).^2/(2*alpha^2))*0.95; +end +if ~isfield(params,'mu') || isempty(params.mu) + params.mu.func = @(x,coeff) x - x.^2/2 + x.^3/3; %@(x) log(1+x) + params.mu.grad = @(x,coeff) 1 - x + x.^2; + params.mu.params = []; +end +% mu.func = @(x,coeff) log((1+x)./(1-x))/2; +% mu.grad = @(x,coeff) 1./(1-x.^2); +% mu.params = []; + +%Finite differencing operator in real space +for i = 1:2 + NI = N(3-i); + ND = N(i); + I = speye(NI); + E = sparse(2:ND,1:ND-1,1,ND,ND); + D = E+E'-2*speye(ND); + %circulant D, periodic boundary condition + D(1,ND) = 1; + D(ND,1) = 1; + if i==1 + L = kron(I,D)/dx(i)^2; + else + L = L + kron(D,I)/dx(i)^2; + end +end +%Finite differencing operator in Fourier space +Lconv = [zeros(1,3); 1,-2,1; zeros(1,3)]/dx(2)^2 + [zeros(3,1), [1;-2;1], zeros(3,1)]/dx(1)^2; +LK = psf2otf(Lconv,N); + +%the Jacobian and mass matrix of the system is Hermitian, so the treatment of pencil is the same for forward and ASA eval +moreoptions = moreodeset('skipInit',true,'Krylov',true, ... +'gmrestol',1e-4,'restart',10); +if isfield(params,'moreoptions') && ~isempty(params.moreoptions) + moreoptions = moreodeset(moreoptions,params.moreoptions); +end +options = odeset; +if isfield(params,'options') && ~isempty(params.options) + options = odeset(options,params.options); +end + +if ~ASA + if isempty(y0) || isscalar(y0) + %initialization + if isempty(y0) + n0 = 0.1; + else + n0 = y0; + end + sigma = 0.01; + rng(1); + y0 = n0 + sigma*randn(N); + y0 = y0(:); + end + if isempty(tspan) + tspan = linspace(0,4,100); + end + t0 = tspan(1); + yp0 = RHS(t0,y0,params); + options = odeset(options,'InitialSlope',yp0,'Jacobian',@(t,y) jacobian(t,y,params)); + moreoptions = moreodeset(moreoptions, ... + 'jacMult',@(xi,t,y,info) jacobian_mult(params,xi,t,y,info), ... + 'pencil',@(xi,t,y,hinvGak,info) pencil(params,xi,t,y,hinvGak,info), ... + 'KrylovDecomp',@(~,~,dfdy,hinvGak) KrylovDecomp(L,dfdy,hinvGak), ... + 'KrylovPrecon',@(x,L,U,hinvGak,~,~,~) KrylovPrecon(LK,params,x,L,U,hinvGak)); + odeFcn = @(t,y) RHS(t,y,params); + + if FSA + moreoptions = moreodeset(moreoptions, ... + 'FSA', true, ... + 'sensFcn', @(t,y) sensFcn(t,y,meta,params), ... + 'ys0', zeros(length(y0),meta.extdata.numParams), ... + 'ysp0', sensFcn(tspan(1),y0,meta,params)); + end + + if sol + y = myode15s(odeFcn,tspan,y0,options,moreoptions); + tout = y.x; + ys = []; + else + [tout,y,ys] = myode15s(odeFcn,tspan,y0,options,moreoptions); + end + varargout = {tout,y,params,ys}; +else + addpath('../../CHACR/GIP') + tdata = tspan; + sol = y0; + ASAQuadNp = 1; + + options = odeset(options,'Jacobian',@(t,y) jacobian(t,sol,params), ... + 'mass', -speye(prod(params.N)),'MassSingular','yes','MStateDependence','none'); + moreoptions = moreodeset(moreoptions, ... + 'jacMult',@(xi,t,y,info) jacobian_mult(params,xi,t,sol,info,true), ... + 'pencil',@(xi,t,y,hinvGak,info) pencil(params,xi,t,sol,hinvGak,info,true), ... + 'KrylovDecomp',@(~,~,dfdy,hinvGak) KrylovDecomp(L,dfdy,hinvGak,true), ... + 'KrylovPrecon',@(x,L,U,hinvGak,~,~,~) KrylovPrecon(LK,params,x,L,U,hinvGak,true)); + if isfield(params,'Csensval') + sensFcnMultiplier = false; + sF = @sensFcn; + else + sensFcnMultiplier = true; + sF = @sensFcn_ASA; + end + moreoptions = moreodeset(moreoptions, ... + 'interpFcn',@(flag,info,tnew,ynew,h,dif,k,idxNonNegative) ASA_gradient(flag,info,tnew,ynew,h,dif,k,idxNonNegative,sol,sF,{params},meta,ASAQuadNp,sensFcnMultiplier)); + + if ~discrete + tspan = [tdata(end),tdata(1)]; + F0 = error(end,:)'; + [y0,yp0] = ASAinit(F0,discrete,params,tspan(1),sol); + options = odeset(options,'InitialSlope',yp0); + moreoptions.linearMult = @(xi,t,info) ASA_mult(t,xi,sol,info,params,tdata,error); + odeFcn = @(t,y) ASA_eqn(t,y,sol,params,tdata,error); + grad = myode15s(odeFcn,tspan,y0,options,moreoptions); + else + y_final = 0; + yp_final = 0; + moreoptions.linearMult = @(xi,t,info) ASA_mult(t,xi,sol,info,params); + odeFcn = @(t,y) ASA_eqn(t,y,sol,params); + %initialize at each time step + y0_list = zeros(n,length(tdata)-1); + yp0_list = y0_list; + for ind = 2:length(tdata) + t0 = tdata(ind); + F0 = error(ind,:)'; + [y0_list(:,ind-1),yp0_list(:,ind-1)] = ASAinit(F0,discrete,params,t0,sol); + end + %serial + grad = zeros(1,meta.extdata.numParams); + for ind = (length(tdata)-1):-1:1 + tspan = [tdata(ind+1),tdata(ind)]; + y0 = y0_list(:,ind)+y_final; + yp0 = yp0_list(:,ind)+yp_final; + options = odeset(options,'InitialSlope',yp0); + [grad_new,y_final,yp_final] = myode15s(odeFcn,tspan,y0,options,moreoptions); + grad = grad + grad_new; + if isnan(y_final) + break; + end + end + end + varargout = {grad}; +end + +end + +function dy = RHS(t,y,params) + %C should be 2D, same below + N = params.N; + dx = params.dx; + C = params.C; + y = reshape(y,N); + mu = customizeFunGrad(params,'mu','fun',y); + mu = mu - ifftn(C .* fftn(y)); + dy = 0; + for i = 1:length(N) + dy = dy + (circshift(mu,1,i)+circshift(mu,-1,i)-2*mu)/dx(i)^2; + end + dy = dy(:); + dy = params.D * dy; +end + +function dfdy = jacobian(t,y,params) + %accommondate its usage through ASA when y is a struct + if isstruct(y) + y = sol_interp(y,t); + end + %this only computes the nonlinear part, as an input to KrylovDecomp + dfdy = customizeFunGrad(params,'mu','grad',y); + dfdy = params.D * dfdy; +end + +function Pargs = KrylovDecomp(L,dfdy,hinvGak,adjoint) + %here dfdy comes from Jacobian + %L is the finite-difference Laplacian operator + n = length(L); + if nargin>3 && adjoint + J = -speye(n) - hinvGak*sparse(1:n,1:n,dfdy).*L; + else + J = speye(n) - hinvGak*L.*sparse(1:n,1:n,dfdy); + end + [L,U] = ilu(J); + Pargs = {L,U}; +end + +function yy = KrylovPrecon(LK,params,x,L,U,hinvGak,adjoint) + %LK is the Fourier transform of the finite difference Laplacian operator + if nargin>6 && adjoint + msign = -1; + else + msign = 1; + end + N = params.N; + C = params.C; + D = params.D; + x = reshape(x,N); + yy = ifftn( fftn(x) ./ (msign + hinvGak*D*LK.*C) ); + yy = yy(:); + yy = U \ (L \ yy); +end + +function yy = jacobian_mult(params,xi,t,y,info,adjoint) + if nargin<6 + adjoint = false; + end + if isequal(info,'force') + yy = jacobian_mult(params,xi,t,y,[],adjoint); + yy = jacobian_mult(params,xi,t,y,yy,adjoint); + elseif isempty(info) + if isstruct(y) + y = sol_interp(y,t); + end + yy = customizeFunGrad(params,'mu','grad',y); + yy = reshape(yy,params.N); + else + N = params.N; + dx = params.dx; + C = params.C; + xi = reshape(xi,N(1),N(2),[]); + if ~adjoint + mu = info .* xi - ifft2(C .* fft2(xi), 'symmetric'); + yy = 0; + for i = 1:length(N) + yy = yy + (circshift(mu,1,i)+circshift(mu,-1,i)-2*mu)/dx(i)^2; + end + else + yy = 0; + for i = 1:length(N) + yy = yy + (circshift(xi,1,i)+circshift(xi,-1,i)-2*xi)/dx(i)^2; + end + yy = info .* yy - ifft2(C .* fft2(yy), 'symmetric'); + end + yy = reshape(yy,prod(N),[]); + yy = params.D * yy; + end +end + +function yy = ASA_mult(t,xi,sol,info,params,varargin) + if isempty(info) + yy = jacobian_mult(params,[],t,sol,[],true); + else + yy = jacobian_mult(params,xi,[],[],info,true); + if ~isempty(varargin) + tdata = varargin{1}; + error = varargin{2}; + [interval,alpha] = interval_counter(tdata,t,length(tdata)-1,2); + source = (error(interval,:)*(1-alpha) + error(interval+1,:)*alpha)'; + yy = yy + source; + end + end +end + +function dy = ASA_eqn(t,y,sol,params,varargin) + %wrapper function for odeFcn (not really needed, mostly just a placeholder, except for daeic) + info = ASA_mult(t,y,sol,[],params); + dy = ASA_mult(t,y,sol,info,params,varargin{:}); +end + +function yy = pencil(params,xi,t,y,hinvGak,info,adjoint) + if nargin < 7 + adjoint = false; + end + if adjoint + msign = -1; + else + msign = 1; + end + yy = jacobian_mult(params,xi,t,y,info,adjoint); + if ~isempty(info) + yy = msign*xi - hinvGak*yy; + end +end + +function dy = sensFcn(t,y,meta,params) + N = params.N; + dx = params.dx; + y = reshape(y,N); + names = fieldnames(meta); + numParams = meta.extdata.numParams; + dy = zeros(numel(y),numParams); + + for i = 1:numel(names) + name = names{i}; + if isequal(name,'extdata') + continue + end + paramsIndex = meta.(name).index; + switch name + case 'mu' + mu = customizeSensEval(params,name,y); + case 'C' + if isfield(params,'Csensval') + mu = - ifft2(params.Csensval .* fftn(y),'symmetric'); + else + mu = -params.Csens(y); + end + case 'D' + mu = customizeFunGrad(params,'mu','fun',y); + mu = mu - ifftn(params.C .* fftn(y)); + end + dyi = 0; + for j = 1:length(N) + dyi = dyi + (circshift(mu,1,j)+circshift(mu,-1,j)-2*mu)/dx(j)^2; + end + dy(:,paramsIndex) = reshape(dyi,[],numel(paramsIndex)); + if ~isequal(name,'D') + dy(:,paramsIndex) = params.D * dy(:,paramsIndex); + end + end +end + +function dy = sensFcn_ASA(t,y,omega,meta,params) + N = params.N; + dx = params.dx; + y = reshape(y,N); + names = fieldnames(meta); + numParams = meta.extdata.numParams; + dy = zeros(1,numParams); + + for i = 1:numel(names) + name = names{i}; + if isequal(name,'extdata') + continue + end + paramsIndex = meta.(name).index; + switch name + case 'mu' + mu = customizeSensEval(params,name,y); + dyi = 0; + for j = 1:length(N) + dyi = dyi + (circshift(mu,1,j)+circshift(mu,-1,j)-2*mu)/dx(j)^2; + end + dy(paramsIndex) = params.D * sum(omega.*reshape(dyi,[],numel(paramsIndex))); + case 'C' + for p = 1:length(paramsIndex) + mu = -params.Csens(y,p); + dyi = 0; + for j = 1:length(N) + dyi = dyi + (circshift(mu,1,j)+circshift(mu,-1,j)-2*mu)/dx(j)^2; + end + dy(paramsIndex(p)) = params.D * sum(omega.*dyi(:)); + end + case 'D' + mu = customizeFunGrad(params,'mu','fun',y); + mu = mu - ifftn(params.C .* fftn(y)); + dyi = 0; + for j = 1:length(N) + dyi = dyi + (circshift(mu,1,j)+circshift(mu,-1,j)-2*mu)/dx(j)^2; + end + dy(paramsIndex) = sum(omega.*reshape(dyi,[],numel(paramsIndex))); + end + end +end + +function [y0,yp0] = ASAinit(F0,discrete,params,t0,sol) + y0 = zeros(size(F0)); + yp0 = -F0; + if discrete + y0 = -yp0; + yp0 = -jacobian_mult(params,y0,t0,sol,'force',true); + end +end + +function varargout = customizeFunGrad(customize,name,request,varargin) + %allow func to output both fun and grad eval + %request can be 'fun','grad',or 'fungrad', and the output will be the requested evaluation in the corresponding order. + %evaluate fun and grad from func function at the same time if grad doesn't exist + funstr = customize.(name); + params = funstr.params; + fungrad = (~isfield(funstr,'grad')); + if fungrad + [fun,grad] = funstr.func(varargin{:},params); + else + if isequal(request,'fun') || isequal(request,'fungrad') + fun = funstr.func(varargin{:},params); + end + if isequal(request,'grad') || isequal(request,'fungrad') + grad = funstr.grad(varargin{:},params); + end + end + switch request + case 'fun' + varargout = {fun}; + case 'grad' + varargout = {grad}; + case 'fungrad' + varargout = {fun,grad}; + end +end diff --git a/solver/spdecomp.m b/solver/spdecomp.m new file mode 100644 index 0000000..37f8955 --- /dev/null +++ b/solver/spdecomp.m @@ -0,0 +1,30 @@ +L = [100,100]; +N = 2^10*[1,1]; +n = prod(N); +kappa = 1; +omega = 3; +sigma = 0.01; + + +rng(1); +y0 = 0.5 + sigma*randn(N); +y0 = fftn(y0); +y0 = y0(:); +[k2,k] = formk(N,L); +k2 = k2(:); + +J = - kappa*k2.^2; + +Nt = 20000; +dt = 0.01; +fps = 30; +outputstep = floor(linspace(1,Nt,fps*20)); +fnlin = @(t,y) spdecomp_nlin(t,y,N,k2,omega); +transform = @(y) reshape(real(ifftn(reshape(y,N))),[],1); +[tout,yout] = odeimexez(fnlin,J,dt,Nt,y0,[],outputstep,[],false,transform); + +myMovie = VideoWriter([largedatapath,'spdecomp_movie']); +set(myMovie,'FrameRate',fps); +open(myMovie); +writeVideo(myMovie,reshape(yout,N(1),N(2),1,[])); +close(myMovie); diff --git a/solver/spdecomp_nlin.m b/solver/spdecomp_nlin.m new file mode 100644 index 0000000..cd1b95d --- /dev/null +++ b/solver/spdecomp_nlin.m @@ -0,0 +1,7 @@ +function f = spdecomp_nlin(t,y,N,k2,omega) + y = reshape(y,N); + yy = real(ifftn(y)); + mu = log(yy./(1-yy))+omega*(1-2*yy); + f = fftn(mu); + f = -f(:).*k2; +end diff --git a/solver/turing_cpu.m b/solver/turing_cpu.m new file mode 100644 index 0000000..69c0e7b --- /dev/null +++ b/solver/turing_cpu.m @@ -0,0 +1,115 @@ +%parameter search +L = [60,60]/2; +N = [256,256]/2; +n = prod(N); +D = [0.02,0.5]; +b = [0.04,-0.15]; +A1 = [0.08,-0.08;0.1,0]; +A2 = -[0.03,0.08]; +lb = [0,0]; +ub = [0.2,0.5]; +u0 = 5; +v0 = 5; +sigma = [0.01,0.01]; +A1lb = [-0.5,-1.5;-0.5,-1.5]; +A1ub = [1.5,0.5;1.5,0.5]; + +rng(1); +reinitialize = true; +if ~reinitialize + u0 = u0 + sigma(1)*randn(N); + v0 = v0 + sigma(2)*randn(N); + yu0 = fftn(u0); + yv0 = fftn(v0); + y0 = [yu0(:); yv0(:)]; +end + +[k2,k] = formk(N,L); + +JD = -k2(:)*D; +J = JD(:) + reshape(ones(n,1)*A2,[],1); + + +saveresult = false; +if saveresult + filepath = '/home/hbozhao/Dropbox (MIT)/2.168 Project/Data/turing_pca'; + mat = matfile(filepath,'Writable',true); + mat.A1 = []; + mat.y = []; +end +Nbatch = 250; +nall = 10000; +%Nbatch = 2; +%nall = 16; +nbatch = nall/(Nbatch*4); %must be integer + +Nt = 1000; +dt = 1; +outputstep = Nt; +thresh = n*1e-5; +termination = @(t,y,~) event_gradient(t,y,k2(:),thresh); +if true + transform = @(y) [reshape(real(ifftn(reshape(y(1:n),N))),[],1);reshape(real(ifftn(reshape(y(n+(1:n)),N))),[],1)]; +else + transform = []; +end +Anorm = norm(A1+diag(A2),inf); +A1 = reshape(A1,1,[]); +nparams = length(A1); +sigma = 0.05*eye(nparams); + +rungpu = false; + +tic; +for batch = 1:nbatch + ybatchall = zeros(4,Nbatch,N(1),N(2),length(outputstep),2); + A1batchall = zeros(4,Nbatch,nparams); + for process = 1:4 + ind = 0; + ybatch = zeros(Nbatch,N(1),N(2),length(outputstep),2); + A1batch = zeros(Nbatch,nparams); + while ind < Nbatch + A1new = A1lb + (A1ub-A1lb).*rand(2); + Anew = A1new+diag(A2); + if LSA(Anew,D) && (norm(Anew,inf)<5*Anorm) + fnlin = @(t,y) turing_nlin_bd(t,y,A1new,b,lb,ub,N); + if reinitialize + y0 = [reshape(fftn(u0 + sigma(1)*randn(N)),[],1); reshape(fftn(v0 + sigma(2)*randn(N)),[],1)]; + end + [~,y,et] = odeimexez(fnlin,J,dt,Nt,y0,[],outputstep,termination,rungpu,transform); + if ~et + A1 = reshape(A1new,1,[]); + ind = ind + 1; + ybatch(ind,:,:,:,:) = permute(reshape(y,N(1),N(2),2,[]),[1,2,4,3]); + A1batch(ind,:) = A1; + end + end + end + A1batchall(process,:,:) = A1batch; + ybatchall(process,:,:,:,:,:) = ybatch; + end + if saveresult + if batch == 1 + mat.A1 = reshape(A1batchall,[],nparams); + mat.y = reshape(ybatchall,[],N(1),N(2),length(outputstep),2); + else + range = (batch-1)*Nbatch*4+(1:Nbatch*4); + mat.A1(range,:) = reshape(A1batchall,[],nparams); + mat.y(range,:,:,:,:) = reshape(ybatchall,[],N(1),N(2),length(outputstep),2); + end + runtime=toc; + disp(['batch ',num2str(batch),' of size ',num2str(Nbatch*4),' saved: Elapsed time (min): ',num2str(runtime/60),' ETA (min): ',num2str(runtime/60*(nbatch-batch)/batch)]); + end +end + +%plot 9 random realizations +figure; +for i=1:9 + subplot(3,3,i); + imagesc(squeeze(mat.y(randi(nall),1:N(1),1:N(2),length(outputstep),1))); + colormap gray; + axis equal; + ax = gca; + ax.XTick=[]; ax.YTick=[]; +end +saveas(gcf,[filepath,'_sample'],'png'); diff --git a/solver/turing_nlin_bd.m b/solver/turing_nlin_bd.m new file mode 100644 index 0000000..e959087 --- /dev/null +++ b/solver/turing_nlin_bd.m @@ -0,0 +1,26 @@ +function f = turing_nlin_bd(t,y,A,b,lb,ub,N) + %constant term b + %A matrix for linear reaction terms (nspecies-by-nspecies) + %lb and ub are lower and upper boundary for the reaction rate for each species + %N is the size of the grid + nspecies = length(b); + y = reshape(y,prod(N),nspecies); + for i=1:nspecies + y(:,i) = reshape(real(ifftn(reshape(y(:,i),N))),[],1); + end + if size(b,2)==1 + b = b'; + end + f = y*A' + b; + if size(lb,2)==1 + lb = lb'; + end + if size(ub,2)==1 + ub = ub'; + end + f = min(max(f,lb),ub); + for i=1:nspecies + f(:,i) = reshape(fftn(reshape(f(:,i),N)),[],1); + end + f = f(:); +end diff --git a/solver/turing_pca.m b/solver/turing_pca.m new file mode 100644 index 0000000..54a179d --- /dev/null +++ b/solver/turing_pca.m @@ -0,0 +1,12 @@ +filepath = '/home/hbozhao/Dropbox (MIT)/2.168 Project/Data/turing_pca'; +mat = matfile(filepath); +ysize = size(mat,'y'); +data = reshape(mat.y(1:ysize(1),1:ysize(2),1:ysize(3),ysize(4),1),ysize(1),[]); +[coeff,score,latent,tsquared] = pca(data); +figure; +semilogy(latent); +saveas(gcf,[filepath,'_latent'],'png'); +figure; +plotmatrix(score(:,1:10)); +saveas(gcf,[filepath,'_latent_pdf'],'png'); +save([filepath,'_result'],'coeff','latent'); diff --git a/solver/turing_pp.m b/solver/turing_pp.m new file mode 100644 index 0000000..ebf476b --- /dev/null +++ b/solver/turing_pp.m @@ -0,0 +1,43 @@ +%image post-processing +filepath = '~/Dropbox (MIT)/2.168 Project/Data/turing_ss'; +mat = matfile(filepath); +ysize = size(mat,'y'); +threshold = 3.5; %a separation of the bimodal distribution of the entire dataset (component 1) +%see for example: +%figure; histogram(mat.y(1:ysize(1),1:ysize(2),1:ysize(3),ysize(4),1) +feature = zeros(ysize(1),8); +index = zeros(ysize(1),1); +ind = 0; +for i=1:ysize(1) + im = squeeze(mat.y(i,1:ysize(2),1:ysize(3),ysize(4),1)); + if ~any(im(:)>threshold) + continue; + end + bw = (im>threshold); + stats = regionprops(bw,'Area','Perimeter'); + area = [stats(:).Area]; + if ~any(area>10) + continue; + end + perimeter = [stats(:).Perimeter]; + circularity = 4*pi*area./perimeter.^2; + ind = ind + 1; + %number of domains + feature(ind,1) = numel(stats); + %mean of domain area + feature(ind,2) = mean(area); + %std of domain area + feature(ind,3) = std(area); + %mean of domain perimeter + feature(ind,4) = mean(perimeter); + feature(ind,5) = std(perimeter); + %min of domain circularity + feature(ind,6) = min(circularity); + %mean of domain circularity + feature(ind,7) = mean(circularity); + %std of domain circularity + feature(ind,8) = std(circularity); + index(ind) = i; +end +feature(ind+1:end,:) = []; +index(ind+1:end) = []; diff --git a/solver/turing_pp_video.m b/solver/turing_pp_video.m new file mode 100644 index 0000000..598158b --- /dev/null +++ b/solver/turing_pp_video.m @@ -0,0 +1,21 @@ +function turing_pp_video(index,video_file,data_file,fps) +%run after turing_pp +%index is the frame to be saved in video +%video_file is the filepath of the video +%data_file is the filepath of the data +if nargin<3 + data_file = '~/Dropbox (MIT)/2.168 Project/Data/turing_ss'; +end +if nargin<4 + fps = 30; +end +mat = load(data_file); +y = mat.y; + +yout = permute(squeeze(y(index,:,:,end,1)),[2,3,4,1]); +yout = yout/max(yout(:)); +myMovie = VideoWriter(video_file); +set(myMovie,'FrameRate',fps); +open(myMovie); +writeVideo(myMovie,yout); +close(myMovie); diff --git a/solver/turing_prototype.m b/solver/turing_prototype.m new file mode 100644 index 0000000..790cba9 --- /dev/null +++ b/solver/turing_prototype.m @@ -0,0 +1,37 @@ +%script for prototyping +L = [60,60]/2; +N = [256,256]/2; +n = prod(N); +D = [0.02,0.5]; +b = [0.04,-0.15]; +A1 = [0.08,-0.08;0.1,0]; +A2 = -[0.03,0.08]; +lb = [0,0]; +ub = [0.2,0.5]; +u0 = 5; +v0 = 5; +sigma = [0.01,0.01]; + +rng(4); +u0 = u0 + sigma(1)*randn(N); +v0 = v0 + sigma(2)*randn(N); +yu0 = fftn(u0); +yv0 = fftn(v0); +y0 = [yu0(:); yv0(:)]; + +[k2,k] = formk(N,L); + +JD = -k2(:)*D; +J = JD(:) + reshape(ones(n,1)*A2,[],1); + +Nt = 10000; +dt = 1; +outputstep = Nt; +thresh(1) = n*1e-5; %threshold for L2 norm of gradient +thresh(2) = 2;%about n*1e-3/8; %threshold for L2 norm of time derivative +termination = @(t,y,yp) event_gradient_ss(t,y,yp,k2(:),thresh); +fnlin = @(t,y) turing_nlin_bd(t,y,A1,b,lb,ub,N); +[t,y,et] = odeimexez(fnlin,J,dt,Nt,y0,[],outputstep,termination); + +figure; +k2real(y(1:n,:),N); diff --git a/solver/turing_ps.m b/solver/turing_ps.m new file mode 100644 index 0000000..772ab4b --- /dev/null +++ b/solver/turing_ps.m @@ -0,0 +1,126 @@ +%parameter search +L = [60,60]/2; +N = [256,256]/2; +n = prod(N); +D = [0.02,0.5]; +b = [0.04,-0.15]; +A1 = [0.08,-0.08;0.1,0]; +A2 = -[0.03,0.08]; +lb = [0,0]; +ub = [0.2,0.5]; +u0 = 5; +v0 = 5; +sigma = [0.01,0.01]; + +rng(1); +u0 = u0 + sigma(1)*randn(N); +v0 = v0 + sigma(2)*randn(N); +yu0 = fftn(u0); +yv0 = fftn(v0); +y0 = [yu0(:); yv0(:)]; + +[k2,k] = formk(N,L); + +JD = -k2(:)*D; +J = JD(:) + reshape(ones(n,1)*A2,[],1); + + +saveresult = false; +if saveresult + filepath = '/home/hbozhao/Dropbox (MIT)/2.168 Project/Data/turing'; + mat = matfile(filepath,'Writable',true); + mat.A1 = []; + mat.y = []; +end +Nsave = 1000; +saveind = 0; + +Nt = 1000; +dt = 1; +outputstep = 100:100:Nt; +% dt = 0.2; +% Nt = 5000; +% outputstep = [1,100:200:1000] ;%[300,1000,2000:1000:Nt]; +nall = 1; +thresh = n*1e-5; +termination = @(t,y,~) event_gradient(t,y,k2(:),thresh); +if saveresult + transform = @(y) [reshape(real(ifftn(reshape(y(1:n),N))),[],1);reshape(real(ifftn(reshape(y(n+(1:n)),N))),[],1)]; +else + transform = []; +end +naccept = 0; +ind = 0; +if saveresult + nblock = Nsave; +else + nblock = nall; +end +Anorm = norm(A1+diag(A2),inf); +A1 = reshape(A1,1,[]); +nparams = length(A1); +sigma = 0.05*eye(nparams); +if saveresult + yall = zeros(nblock,N(1),N(2),length(outputstep),2); +else + yall = zeros(nblock,n*2,length(outputstep)); +end +A1all = zeros(nblock,nparams); + +rungpu = false; +if rungpu + y0 = gpuArray(y0); + A1 = gpuArray(A1); + b = gpuArray(b); + lb = gpuArray(lb); + ub = gpuArray(ub); + J = gpuArray(J); + k2 = gpuArray(k2); + A1all = gpuArray(A1all); + yall = gpuArray(yall); +end +tic; +while naccept < nall + A1new = A1 + mvnrnd(zeros(1,nparams),sigma); + A1new = reshape(A1new,2,2); + Anew = A1new+diag(A2); + if LSA(Anew,D) && (norm(Anew,inf)<5*Anorm) + fnlin = @(t,y) turing_nlin_bd(t,y,A1new,b,lb,ub,N); + [~,y,et] = odeimexez(fnlin,J,dt,Nt,y0,[],outputstep,termination,rungpu,transform); + if ~et + A1 = reshape(A1new,1,[]); + naccept = naccept + 1; + ind = ind + 1; + if saveresult + yall(ind,:,:,:,:) = permute(reshape(y,N(1),N(2),2,[]),[1,2,4,3]); + else + yall(ind,:,:) = y; + end + A1all(ind,:) = A1; + runtime=toc; + disp(['case ',num2str(naccept),' finished: Elapsed time (min): ',num2str(runtime/60),' ETA (min): ',num2str(runtime/60*(nall-naccept)/naccept)]); + if saveresult && mod(naccept,Nsave)==0 + if naccept == Nsave + mat.A1 = gather(A1all); + mat.y = gather(yall); + else + mat.A1(saveind+(1:Nsave),:) = gather(A1all); + mat.y(saveind+(1:Nsave),:,:,:,:) = gather(yall); + end + yall = zeros(nblock,N(1),N(2),length(outputstep),2,'gpuArray'); + A1all = zeros(nblock,nparams,'gpuArray'); + saveind = saveind+Nsave; + ind = 0; + end + end + end +end + +if ~saveresult + figure; + if ndims(yall) == 3 + k2real(reshape(permute(yall(1:naccept,1:n,:),[1,3,2]),[],n).',N,[],'colorbar','on'); + else + k2real(yall(1:naccept,1:n,:).',N);%,[],'GridSize',[9,9]); + end +end diff --git a/solver/turing_ss.m b/solver/turing_ss.m new file mode 100644 index 0000000..d32e2ca --- /dev/null +++ b/solver/turing_ss.m @@ -0,0 +1,116 @@ +%parameter search +L = [60,60]/2; +N = [256,256]/2; +n = prod(N); +D = [0.02,0.5]; +b = [0.04,-0.15]; +A1 = [0.08,-0.08;0.1,0]; +A2 = -[0.03,0.08]; +lb = [0,0]; +ub = [0.2,0.5]; +u0 = 5; +v0 = 5; +sigma = [0.01,0.01]; +A1lb = [-0.5,-1.5;-0.5,-1.5]; +A1ub = [1.5,0.5;1.5,0.5]; + +rng(1); +reinitialize = true; +if ~reinitialize + u0 = u0 + sigma(1)*randn(N); + v0 = v0 + sigma(2)*randn(N); + yu0 = fftn(u0); + yv0 = fftn(v0); + y0 = [yu0(:); yv0(:)]; +end + +[k2,k] = formk(N,L); + +JD = -k2(:)*D; +J = JD(:) + reshape(ones(n,1)*A2,[],1); + + +saveresult = true; +if saveresult + filepath = '/home/hbozhao/Dropbox (MIT)/2.168 Project/Data/turing_ss'; + mat = matfile(filepath,'Writable',true); + mat.A1 = []; + mat.y = []; +end +Nbatch = 250; +nall = 10000; +%Nbatch = 2; +%nall = 16; +nbatch = nall/(Nbatch*4); %must be integer + +Nt = 10000; +dt = 1; +outputstep = Nt; +thresh(1) = n*1e-5; %threshold for L2 norm of gradient +thresh(2) = 2;%about n*1e-3/8; %threshold for L2 norm of time derivative +termination = @(t,y,yp) event_gradient_ss(t,y,yp,k2(:),thresh); +if saveresult + transform = @(y) [reshape(real(ifftn(reshape(y(1:n),N))),[],1);reshape(real(ifftn(reshape(y(n+(1:n)),N))),[],1)]; +else + transform = []; +end +Anorm = norm(A1+diag(A2),inf); +A1 = reshape(A1,1,[]); +nparams = length(A1); +sigma = 0.05*eye(nparams); + +rungpu = false; + +tic; +for batch = 1:nbatch + ybatchall = zeros(4,Nbatch,N(1),N(2),length(outputstep),2); + A1batchall = zeros(4,Nbatch,nparams); + parfor process = 1:4 + ind = 0; + ybatch = zeros(Nbatch,N(1),N(2),length(outputstep),2); + A1batch = zeros(Nbatch,nparams); + while ind < Nbatch + A1new = A1lb + (A1ub-A1lb).*rand(2); + Anew = A1new+diag(A2); + if LSA(Anew,D) && (norm(Anew,inf)<5*Anorm) + fnlin = @(t,y) turing_nlin_bd(t,y,A1new,b,lb,ub,N); + if reinitialize + y0 = [reshape(fftn(u0 + sigma(1)*randn(N)),[],1); reshape(fftn(v0 + sigma(2)*randn(N)),[],1)]; + end + [~,y,et] = odeimexez(fnlin,J,dt,Nt,y0,[],outputstep,termination,rungpu,transform); + if et ~= 1 + A1 = reshape(A1new,1,[]); + ind = ind + 1; + ybatch(ind,:,:,:,:) = permute(reshape(y,N(1),N(2),2,[]),[1,2,4,3]); + A1batch(ind,:) = A1; + end + end + end + A1batchall(process,:,:) = A1batch; + ybatchall(process,:,:,:,:,:) = ybatch; + end + if saveresult + if batch == 1 + mat.A1 = reshape(A1batchall,[],nparams); + mat.y = reshape(ybatchall,[],N(1),N(2),length(outputstep),2); + else + range = (batch-1)*Nbatch*4+(1:Nbatch*4); + mat.A1(range,:) = reshape(A1batchall,[],nparams); + mat.y(range,:,:,:,:) = reshape(ybatchall,[],N(1),N(2),length(outputstep),2); + end + runtime=toc; + disp(['batch ',num2str(batch),' of size ',num2str(Nbatch*4),' saved: Elapsed time (min): ',num2str(runtime/60),' ETA (min): ',num2str(runtime/60*(nbatch-batch)/batch)]); + end +end + +%plot 9 random realizations +figure; +for i=1:9 + subplot(3,3,i); + imagesc(squeeze(mat.y(randi(nall),1:N(1),1:N(2),length(outputstep),1))); + colormap gray; + axis equal; + ax = gca; + ax.XTick=[]; ax.YTick=[]; +end +saveas(gcf,[filepath,'_sample'],'png'); diff --git a/solver/turing_ss_2_params.m b/solver/turing_ss_2_params.m new file mode 100644 index 0000000..fd766cc --- /dev/null +++ b/solver/turing_ss_2_params.m @@ -0,0 +1,118 @@ +%parameter search +L = [60,60]/2; +N = [256,256]/2; +n = prod(N); +D = [0.02,0.5]; +b = [0.04,-0.15]; +A1 = [0.08,-0.08;0.1,0]; +A2 = -[0.03,0.08]; +lb = [0,0]; +ub = [0.2,0.5]; +u0 = 5; +v0 = 5; +sigma = [0.01,0.01]; +mat_ss = matfile('/home/hbozhao/Dropbox (MIT)/2.168 Project/Data/turing_ss'); +A1_ss = mean(mat_ss.A1,1); +A1lb = [-0.5,A1_ss(3);-0.5,A1_ss(4)]; +A1ub = [1.5,A1_ss(3);1.5,A1_ss(4)]; + +rng(1); +reinitialize = true; +if ~reinitialize + u0 = u0 + sigma(1)*randn(N); + v0 = v0 + sigma(2)*randn(N); + yu0 = fftn(u0); + yv0 = fftn(v0); + y0 = [yu0(:); yv0(:)]; +end + +[k2,k] = formk(N,L); + +JD = -k2(:)*D; +J = JD(:) + reshape(ones(n,1)*A2,[],1); + + +saveresult = true; +if saveresult + filepath = '/home/hbozhao/Dropbox (MIT)/2.168 Project/Data/turing_ss_2_params'; + mat = matfile(filepath,'Writable',true); + mat.A1 = []; + mat.y = []; +end +Nbatch = 250; +nall = 10000; +%Nbatch = 2; +%nall = 16; +nbatch = nall/(Nbatch*4); %must be integer + +Nt = 10000; +dt = 1; +outputstep = Nt; +thresh(1) = n*1e-5; %threshold for L2 norm of gradient +thresh(2) = 2;%about n*1e-3/8; %threshold for L2 norm of time derivative +termination = @(t,y,yp) event_gradient_ss(t,y,yp,k2(:),thresh); +if saveresult + transform = @(y) [reshape(real(ifftn(reshape(y(1:n),N))),[],1);reshape(real(ifftn(reshape(y(n+(1:n)),N))),[],1)]; +else + transform = []; +end +Anorm = norm(A1+diag(A2),inf); +A1 = reshape(A1,1,[]); +nparams = length(A1); +sigma = 0.05*eye(nparams); + +rungpu = false; + +tic; +for batch = 1:nbatch + ybatchall = zeros(4,Nbatch,N(1),N(2),length(outputstep),2); + A1batchall = zeros(4,Nbatch,nparams); + parfor process = 1:4 + ind = 0; + ybatch = zeros(Nbatch,N(1),N(2),length(outputstep),2); + A1batch = zeros(Nbatch,nparams); + while ind < Nbatch + A1new = A1lb + (A1ub-A1lb).*rand(2); + Anew = A1new+diag(A2); + if LSA(Anew,D) && (norm(Anew,inf)<5*Anorm) + fnlin = @(t,y) turing_nlin_bd(t,y,A1new,b,lb,ub,N); + if reinitialize + y0 = [reshape(fftn(u0 + sigma(1)*randn(N)),[],1); reshape(fftn(v0 + sigma(2)*randn(N)),[],1)]; + end + [~,y,et] = odeimexez(fnlin,J,dt,Nt,y0,[],outputstep,termination,rungpu,transform); + if et ~= 1 + A1 = reshape(A1new,1,[]); + ind = ind + 1; + ybatch(ind,:,:,:,:) = permute(reshape(y,N(1),N(2),2,[]),[1,2,4,3]); + A1batch(ind,:) = A1; + end + end + end + A1batchall(process,:,:) = A1batch; + ybatchall(process,:,:,:,:,:) = ybatch; + end + if saveresult + if batch == 1 + mat.A1 = reshape(A1batchall,[],nparams); + mat.y = reshape(ybatchall,[],N(1),N(2),length(outputstep),2); + else + range = (batch-1)*Nbatch*4+(1:Nbatch*4); + mat.A1(range,:) = reshape(A1batchall,[],nparams); + mat.y(range,:,:,:,:) = reshape(ybatchall,[],N(1),N(2),length(outputstep),2); + end + runtime=toc; + disp(['batch ',num2str(batch),' of size ',num2str(Nbatch*4),' saved: Elapsed time (min): ',num2str(runtime/60),' ETA (min): ',num2str(runtime/60*(nbatch-batch)/batch)]); + end +end + +%plot 9 random realizations +% figure; +% for i=1:9 +% subplot(3,3,i); +% imagesc(squeeze(mat.y(randi(nall),1:N(1),1:N(2),length(outputstep),1))); +% colormap gray; +% axis equal; +% ax = gca; +% ax.XTick=[]; ax.YTick=[]; +% end +% saveas(gcf,[filepath,'_sample'],'png'); diff --git a/solver/turing_video.m b/solver/turing_video.m new file mode 100644 index 0000000..544c8e6 --- /dev/null +++ b/solver/turing_video.m @@ -0,0 +1,68 @@ +%parameter search +L = [60,60]/2; +N = [256,256]/2; +n = prod(N); +D = [0.02,0.5]; +b = [0.04,-0.15]; +A1 = [0.08,-0.08;0.1,0]; +A2 = -[0.03,0.08]; +lb = [0,0]; +ub = [0.2,0.5]; +u0 = 5; +v0 = 5; +sigma = [0.01,0.01]; +A1lb = [-0.5,-1.5;-0.5,-1.5]; +A1ub = [1.5,0.5;1.5,0.5]; +mat = matfile('/home/hbozhao/Dropbox (MIT)/2.168 Project/Data/turing_ss.mat'); + +rng(1); +u0 = u0 + sigma(1)*randn(N); +v0 = v0 + sigma(2)*randn(N); +yu0 = fftn(u0); +yv0 = fftn(v0); +y0 = [yu0(:); yv0(:)]; + +[k2,k] = formk(N,L); + +JD = -k2(:)*D; +J = JD(:) + reshape(ones(n,1)*A2,[],1); + +rungpu = false; +Nt = 1000; +dt = 1; +outputstep = floor(linspace(1,Nt,300)); +transform = @(y) [reshape(real(ifftn(reshape(y(1:n),N))),[],1);reshape(real(ifftn(reshape(y(n+(1:n)),N))),[],1)]; + +for ind = 2%1:2 + switch ind + case 1 + A1 = [0.08,-0.08;0.1,0]; + case 2 + A1 = reshape(mat.A1(1021,1:4),2,2); + end + fnlin = @(t,y) turing_nlin_bd(t,y,A1,b,lb,ub,N); + [t,y,et] = odeimexez(fnlin,J,dt,Nt,y0,[],outputstep,[],rungpu,transform); + y = reshape(y,N(1),N(2),2,[]); + ymax = max(max(max(y,[],1),[],2),[],4); + + video_file = ['/home/hbozhao/Dropbox (MIT)/MIT Courses/2.168/2.168 Project/Final/movie_',num2str(ind)]; + myMovie = VideoWriter(video_file); + set(myMovie,'FrameRate',30); + open(myMovie); + for i = 1:length(t) + for j = 1:2 + subplot(1,2,j) + imagesc(y(:,:,j,i)); + a = gca; + a.XTick = []; a.YTick = []; + axis tight; axis equal; + a.CLim = [0,ymax(j)]; + colormap('gray') + colorbar; + end + F = print('-RGBImage'); + writeVideo(myMovie,F); + delete(findall(gcf,'Type','Axes')); + end + close(myMovie); +end diff --git a/train.py b/train.py new file mode 100644 index 0000000..2cf6359 --- /dev/null +++ b/train.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +import reacdiff.parsing as parsing +import reacdiff.train.run_training as run_training + + +if __name__ == '__main__': + args = parsing.parse_train_args() + run_training.run_training(args)