diff --git a/examples/example3/example3_withaxisymm.ipynb b/examples/example3/example3_withaxisymm.ipynb index 93b402db..d91a4fca 100644 --- a/examples/example3/example3_withaxisymm.ipynb +++ b/examples/example3/example3_withaxisymm.ipynb @@ -425,7 +425,7 @@ " \"final_t\": 1,\n", " \"initial_dt\": 0.01,\n", " \"time_precision\": 6,\n", - " \"attempt_timestep_restart_on_divergence\": True\n", + " # \"attempt_timestep_restart_on_divergence\": True\n", " }\n", ")\n", "config_cur.flags.update({\"axisymmetric_model\": True})" @@ -627,7 +627,7 @@ " \"final_t\": 1,\n", " \"initial_dt\": 0.01,\n", " \"time_precision\": 6,\n", - " \"attempt_timestep_restart_on_divergence\": True,\n", + " # \"attempt_timestep_restart_on_divergence\": True,\n", " }\n", " )\n", " config_cur.flags.update({\"axisymmetric_model\": True})\n", diff --git a/smart/mesh_tools.py b/smart/mesh_tools.py index 6d4c2ec7..576a1be7 100644 --- a/smart/mesh_tools.py +++ b/smart/mesh_tools.py @@ -1438,16 +1438,19 @@ def load_mesh( if extra_keys is None: extra_keys = [] - if not pathlib.Path(filename).is_file(): + if isinstance(filename, str): + filename = pathlib.Path(filename) + + if not filename.is_file(): raise FileNotFoundError(f"File {filename} does not exists") if mesh is None: mesh = d.Mesh(comm) - with d.HDF5File(comm, pathlib.Path(filename).with_suffix(".h5").as_posix(), "r") as hdf5: + with d.HDF5File(comm, filename.with_suffix(".h5").as_posix(), "r") as hdf5: hdf5.read(mesh, "/mesh", False) - dim = mesh.geometric_dimension() + dim = mesh.topology().dim() # geometric_dimension() mf_cell = d.MeshFunction("size_t", mesh, dim) mf_facet = d.MeshFunction("size_t", mesh, dim - 1) subdomains = [] diff --git a/smart/model.py b/smart/model.py index a5411d2c..e11877bc 100644 --- a/smart/model.py +++ b/smart/model.py @@ -474,6 +474,12 @@ def _init_2_1_reactions_to_symbolic_strings(self): raise ValueError( "Reaction %s does not seem to have an associated equation" % reaction.name ) + if reaction.eqn_f_str == "": + reaction.eqn_str = f"-{reaction.eqn_r_str}" + elif reaction.eqn_r_str == "": + reaction.eqn_str = f"{reaction.eqn_f_str}" + else: + reaction.eqn_str = f"{reaction.eqn_f_str}-{reaction.eqn_r_str}" def _init_2_2_check_reaction_validity(self): """Confirms that all reactions have parameters/species defined""" @@ -986,7 +992,11 @@ def _init_4_7_set_initial_conditions(self): # restrict to specified subdomain u_cur = self.cc[species.compartment_name].u[ukey] u_new = create_restriction(u_cur, species.subdomain_data, species.subdomain_val) - u_cur.assign(u_new) + values = u_cur.vector().get_local() + values_new = u_new.vector().get_local() + values[species.dof_map] = values_new[species.dof_map] + u_cur.vector().set_local(values) + u_cur.vector().apply("insert") def _init_5_1_reactions_to_fluxes(self): """Convert reactions to flux objects""" diff --git a/smart/model_assembly.py b/smart/model_assembly.py index c37320ae..ae163154 100644 --- a/smart/model_assembly.py +++ b/smart/model_assembly.py @@ -219,8 +219,8 @@ def print_to_latex( self, properties_to_print=None, max_col_width=None, - sig_figs=2, - return_df=True, + sig_figs=3, + return_df=False, ): """ Print object properties in latex format. @@ -242,7 +242,33 @@ def print_to_latex( for row in range(df.shape[0]): for col in range(df.shape[1]): - if isinstance(df.iat[row, col], str): + if df.columns[col] == "eqn_str": + cur_str = df.iat[row, col] + cur_str = "$" + cur_str + "$" + cur_str = cur_str.replace("**", "^") + idx = 0 + while idx < len(cur_str): + if cur_str[idx] == "_": + cur_str = cur_str[0 : idx + 1] + "{" + cur_str[idx + 1 :] + isMath = False + testIdx = idx + 2 + while not isMath: + if not (cur_str[testIdx].isalnum() or cur_str[testIdx] == "_"): + if cur_str[testIdx] == "*": + cur_str = cur_str[0:testIdx] + "} " + cur_str[testIdx + 1 :] + else: + cur_str = cur_str[0:testIdx] + "}" + cur_str[testIdx:] + isMath = True + else: + testIdx += 1 + idx = testIdx + 2 + elif cur_str[idx] == "*": + cur_str = cur_str[0:idx] + " " + cur_str[idx + 1 :] + idx += 1 + else: + idx += 1 + df.iloc[row, col] = cur_str + elif isinstance(df.iat[row, col], str): cur_str = df.iat[row, col] if "_" in cur_str: df.iloc[row, col] = cur_str.replace("_", "\_") @@ -259,15 +285,15 @@ def print_to_latex( new_list[i] = "`" cur_str = "".join(new_list) df.iloc[row, col] = cur_str - for col in df.columns: - # Convert quantity objects to unit - if isinstance(df[col].iloc[0], pint.Quantity): - # if tablefmt=='latex': - df[col] = df[col].apply(lambda x: f"${x:0.{sig_figs}e~Lx}$") - - if col == "idx": - df = df.drop("idx", axis=1) + # Convert quantity objects to unit + elif isinstance(df.iat[row, col], pint.Quantity): + x = df.iat[row, col] + if isinstance(x.magnitude, str): + df.iloc[row, col] = f"{x:s~P}" + else: + df.iloc[row, col] = f"${x:0.{sig_figs}e~Lx}$" + for col in df.columns: if "_" in col: df = df.rename(columns={col: col.replace("_", "\_")}) @@ -275,7 +301,7 @@ def print_to_latex( return df else: with pandas.option_context("max_colwidth", 1000): - logger.info(df.to_latex(escape=False, longtable=True, index=False)) + logger.info(df.to_latex(escape=False, longtable=True, index=True)) def get_pandas_dataframe_formatted( self, @@ -326,11 +352,14 @@ def print( ) # # Change certain df entries to best format for printing - for col in df.columns: - # Convert quantity objects to unit - if isinstance(df[col].iloc[0], pint.Quantity): - # if tablefmt=='latex': - df[col] = df[col].apply(lambda x: f"{x:0.{sig_figs}e~P}") + for row in range(df.shape[0]): + for col in range(df.shape[1]): + if isinstance(df.iat[row, col], pint.Quantity): + x = df.iat[row, col] + if isinstance(x.magnitude, str): + df.iloc[row, col] = f"{x:s~P}" + else: + df.iloc[row, col] = f"{x:0.{sig_figs}e~P}" # print to file if filename is None: @@ -447,7 +476,7 @@ def __init__(self): self.properties_to_print = [ "_quantity", - "is_time_dependent", + # "is_time_dependent", "sym_expr", "notes", "group", @@ -760,8 +789,7 @@ def __init__(self): self.properties_to_print = [ "compartment_name", "_Diffusion", - "initial_condition", - "concentration_units", + "_Initial_Concentration", ] def print( @@ -774,33 +802,9 @@ def print( for s in self: s.D_quantity s.latex_name + s.initial_condition_quantity super().print(tablefmt, self.properties_to_print, filename, max_col_width) - def print_to_latex( - self, - properties_to_print=None, - max_col_width=None, - sig_figs=2, - return_df=False, - ): - properties_to_print = ["_latex_name"] - properties_to_print.extend(self.properties_to_print) - df = super().print_to_latex(properties_to_print, max_col_width, sig_figs, return_df=True) - # fix dof_index - for col in df.columns: - if col == "dof_index": - df[col] = df[col].astype(int) - # fix name - # get the column of df that contains the name - # this can be more robust - # df.columns - - if return_df: - return df - else: - with pandas.option_context("max_colwidth", 1000): - logger.info(df.to_latex(escape=False, longtable=True, index=False)) - @dataclass class Species(ObjectInstance): @@ -841,7 +845,6 @@ class Species(ObjectInstance): def to_dict(self): "Convert to a dict that can be used to recreate the object." keys_to_keep = [ - "name", "initial_condition", "concentration_units", "D", @@ -1139,7 +1142,7 @@ class ReactionContainer(ObjectContainer): def __init__(self): super().__init__(Reaction) - self.properties_to_print = ["lhs", "rhs", "eqn_f_str", "eqn_r_str"] + self.properties_to_print = ["lhs", "rhs", "eqn_str", "topology"] def print( self, @@ -1217,6 +1220,8 @@ class Reaction(ObjectInstance): track_value: bool = False eqn_f_str: str = "" eqn_r_str: str = "" + eqn_str: str = "" + topology: str = "" group: str = "" axisymm: bool = False has_subdomain: bool = False @@ -1235,6 +1240,7 @@ def to_dict(self): "track_value", "eqn_f_str", "eqn_r_str", + "eqn_str", "group", "axisymm", ]