PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/base/rheology/flowlaw_factory.cc

Go to the documentation of this file.
00001 // Copyright (C) 2009, 2010, 2011 Jed Brown, Ed Bueler and Constantine Khroulev
00002 //
00003 // This file is part of PISM.
00004 //
00005 // PISM is free software; you can redistribute it and/or modify it under the
00006 // terms of the GNU General Public License as published by the Free Software
00007 // Foundation; either version 2 of the License, or (at your option) any later
00008 // version.
00009 //
00010 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY
00011 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00012 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00013 // details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with PISM; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 #include "flowlaw_factory.hh"
00020 #include "pism_const.hh"
00021 
00022 #undef ALEN
00023 #define ALEN(a) (sizeof(a)/sizeof(a)[0])
00024 
00025 IceFlowLawFactory::IceFlowLawFactory(MPI_Comm c,const char pre[], const NCConfigVariable &conf) : config(conf)
00026 {
00027   comm = c;
00028   prefix[0] = 0;
00029   if (pre) {
00030     PetscStrncpy(prefix,pre,sizeof(prefix));
00031   }
00032   if (registerAll()) {
00033     PetscPrintf(comm,"IceFlowLawFactory::registerAll returned an error but we're in a constructor\n");
00034     PISMEnd();
00035   }
00036   if (setType(ICE_PB)) {       // Set's a default type
00037     PetscPrintf(comm,"IceFlowLawFactory::setType(\"%s\") returned an error, but we're in a constructor\n",ICE_PB);
00038     PISMEnd();
00039   }
00040 }
00041 
00042 IceFlowLawFactory::~IceFlowLawFactory()
00043 {
00044   PetscFListDestroy(&type_list);
00045 }
00046 
00047 #undef __FUNCT__
00048 #define __FUNCT__ "IceFlowLawFactory::registerType"
00049 PetscErrorCode IceFlowLawFactory::registerType(const char tname[],
00050                                         PetscErrorCode(*icreate)(MPI_Comm,const char[],const NCConfigVariable &, IceFlowLaw**))
00051 {
00052   PetscErrorCode ierr;
00053 
00054   PetscFunctionBegin;
00055   ierr = PetscFListAdd(&type_list,tname,NULL,(void(*)(void))icreate);CHKERRQ(ierr);
00056   PetscFunctionReturn(0);
00057 }
00058 
00059 
00060 static PetscErrorCode create_custom(MPI_Comm comm,const char pre[], const NCConfigVariable &config, IceFlowLaw **i) {
00061   *i = new (CustomGlenIce)(comm, pre, config);  return 0;
00062 }
00063 static PetscErrorCode create_pb(MPI_Comm comm,const char pre[], const NCConfigVariable &config, IceFlowLaw **i) {
00064   *i = new (ThermoGlenIce)(comm, pre, config);  return 0;
00065 }
00066 static PetscErrorCode create_gpbld(MPI_Comm comm,const char pre[], const NCConfigVariable &config, IceFlowLaw **i) {
00067   *i = new (GPBLDIce)(comm, pre, config);  return 0;
00068 }
00069 static PetscErrorCode create_hooke(MPI_Comm comm,const char pre[], const NCConfigVariable &config, IceFlowLaw **i) {
00070   *i = new (HookeIce)(comm, pre, config);  return 0;
00071 }
00072 static PetscErrorCode create_arr(MPI_Comm comm,const char pre[], const NCConfigVariable &config, IceFlowLaw **i) {
00073   *i = new (ThermoGlenArrIce)(comm, pre, config);  return 0;
00074 }
00075 static PetscErrorCode create_arrwarm(MPI_Comm comm,const char pre[], const NCConfigVariable &config, IceFlowLaw **i) {
00076   *i = new (ThermoGlenArrIceWarm)(comm, pre, config);  return 0;
00077 }
00078 static PetscErrorCode create_hybrid(MPI_Comm comm,const char pre[], const NCConfigVariable &config, IceFlowLaw **i) {
00079   *i = new (HybridIce)(comm, pre, config);  return 0;
00080 }
00081 
00082 
00083 #undef __FUNCT__
00084 #define __FUNCT__ "IceFlowLawFactory::registerAll"
00085 PetscErrorCode IceFlowLawFactory::registerAll()
00086 {
00087   PetscErrorCode ierr;
00088 
00089   PetscFunctionBegin;
00090   ierr = PetscMemzero(&type_list,sizeof(type_list));CHKERRQ(ierr);
00091   ierr = registerType(ICE_CUSTOM, &create_custom); CHKERRQ(ierr);
00092   ierr = registerType(ICE_PB,     &create_pb);     CHKERRQ(ierr);
00093   ierr = registerType(ICE_GPBLD,  &create_gpbld);  CHKERRQ(ierr);
00094   ierr = registerType(ICE_HOOKE,  &create_hooke);  CHKERRQ(ierr);
00095   ierr = registerType(ICE_ARR,    &create_arr);    CHKERRQ(ierr);
00096   ierr = registerType(ICE_ARRWARM,&create_arrwarm);CHKERRQ(ierr);
00097   ierr = registerType(ICE_HYBRID, &create_hybrid); CHKERRQ(ierr);
00098   PetscFunctionReturn(0);
00099 }
00100 
00101 
00102 #undef __FUNCT__
00103 #define __FUNCT__ "IceFlowLawFactory::setType"
00104 PetscErrorCode IceFlowLawFactory::setType(const char type[])
00105 {
00106   void (*r)(void);
00107   PetscErrorCode ierr;
00108 
00109   PetscFunctionBegin;
00110   ierr = PetscFListFind(type_list,comm,type,(void(**)(void))&r);CHKERRQ(ierr);
00111   if (!r) {
00112     ierr = PetscPrintf(comm, "PISM ERROR: Selected ice type \"%s\" is not available.\n",type); CHKERRQ(ierr);
00113     PISMEnd();
00114   }
00115   ierr = PetscStrncpy(type_name,type,sizeof(type_name));CHKERRQ(ierr);
00116   PetscFunctionReturn(0);
00117 }
00118 
00119 #undef __FUNCT__
00120 #define __FUNCT__ "IceFlowLawFactory::setFromOptions"
00121 PetscErrorCode IceFlowLawFactory::setFromOptions()
00122 {
00123   PetscErrorCode ierr;
00124   PetscTruth flg;
00125   char my_type_name[256];
00126 
00127   PetscFunctionBegin;
00128   // These options will choose Goldsby-Kohlstedt ice by default (see IceModel::setFromOptions()) but if a derived class
00129   // uses a different initialization procedure, we'll recognize them here as well.  A better long-term solution would be
00130   // to separate tracking of grain size from a particular flow law (since in principle they are unrelated) but since
00131   // HYBRID is the only one that currently uses grain size, this solution is acceptable.
00132   ierr = PetscOptionsHasName(prefix, "-gk_age", &flg); CHKERRQ(ierr);
00133   if (flg) {
00134     ierr = setType(ICE_HYBRID);CHKERRQ(ierr);
00135   }
00136   // -gk 0 does not make sense, so using PetscOptionsHasName is OK.
00137   ierr = PetscOptionsHasName(prefix, "-gk", &flg); CHKERRQ(ierr);
00138   if (flg) {
00139     ierr = setType(ICE_HYBRID);CHKERRQ(ierr);
00140   }
00141   ierr = PetscOptionsBegin(comm,prefix,"IceFlowLawFactory options","IceFlowLaw");CHKERRQ(ierr);
00142   {
00143     ierr = PetscOptionsList("-ice_type","Ice type","IceFlowLawFactory::setType",
00144                             type_list,type_name,my_type_name,sizeof(my_type_name),&flg);CHKERRQ(ierr);
00145     if (flg) {ierr = setType(my_type_name);CHKERRQ(ierr);}
00146   }
00147   ierr = PetscOptionsEnd();CHKERRQ(ierr);
00148   
00149 //  ierr = PetscPrintf(comm,"IceFlowLawFactory::type_name=%s at end of IceFlowLawFactory::setFromOptions()\n",
00150 //                     type_name); CHKERRQ(ierr);
00151   PetscFunctionReturn(0);
00152 }
00153 
00154 
00155 #undef __FUNCT__
00156 #define __FUNCT__ "IceFlowLawFactory::create"
00157 PetscErrorCode IceFlowLawFactory::create(IceFlowLaw **inice)
00158 {
00159   PetscErrorCode ierr,(*r)(MPI_Comm,const char[],const NCConfigVariable &,IceFlowLaw**);
00160   IceFlowLaw *ice;
00161 
00162   PetscFunctionBegin;
00163   PetscValidPointer(inice,3);
00164   *inice = 0;
00165   // find the function that can create selected ice type:
00166   ierr = PetscFListFind(type_list,comm,type_name,(void(**)(void))&r);CHKERRQ(ierr);
00167   if (!r) SETERRQ1(1,"Selected Ice type %s not available, but we shouldn't be able to get here anyway",type_name);
00168   // create an IceFlowLaw instance:
00169   ierr = (*r)(comm,prefix,config,&ice);CHKERRQ(ierr);
00170   *inice = ice;
00171   PetscFunctionReturn(0);
00172 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines